Salesforce.com interface to directly access Salesforce.com

Dependencies:   HTTPClient-SSL MbedJSONValue

Dependents:   df-2014-salesforce-hrm-k64f

Fork of SalesforceInterface by Doug Anson

Committer:
ansond
Date:
Thu Sep 25 05:35:05 2014 +0000
Revision:
20:0d6abaf6d7c5
Parent:
19:6a791e5449b3
Child:
21:e5a4471a46fb
additional handling of error messages that come back in error conditions

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ansond 0:518b1ca956fc 1 /* Copyright C2014 ARM, MIT License
ansond 0:518b1ca956fc 2 *
ansond 9:a254fcd904be 3 * Author: Doug Anson (doug.anson@arm.com)
ansond 9:a254fcd904be 4 *
ansond 0:518b1ca956fc 5 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
ansond 0:518b1ca956fc 6 * and associated documentation files the "Software", to deal in the Software without restriction,
ansond 0:518b1ca956fc 7 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
ansond 0:518b1ca956fc 8 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
ansond 0:518b1ca956fc 9 * furnished to do so, subject to the following conditions:
ansond 0:518b1ca956fc 10 *
ansond 0:518b1ca956fc 11 * The above copyright notice and this permission notice shall be included in all copies or
ansond 0:518b1ca956fc 12 * substantial portions of the Software.
ansond 0:518b1ca956fc 13 *
ansond 16:3d160f224084 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
ansond 0:518b1ca956fc 15 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
ansond 0:518b1ca956fc 16 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
ansond 0:518b1ca956fc 17 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
ansond 0:518b1ca956fc 18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
ansond 0:518b1ca956fc 19 */
ansond 0:518b1ca956fc 20
ansond 0:518b1ca956fc 21 // Tuneables
ansond 0:518b1ca956fc 22 #define SF_OAUTH_TOKEN_URL "https://login.salesforce.com/services/oauth2/token"
ansond 0:518b1ca956fc 23 #define SF_OAUTH_REQUEST_BODY "grant_type=password&client_id=%s&client_secret=%s&username=%s&password=%s"
ansond 0:518b1ca956fc 24 #define SF_HTTP_AUTH_HEADER "Authorization: Bearer %s"
ansond 0:518b1ca956fc 25
ansond 15:89044c68ad36 26 // search tokens for URLS in salesforce token
ansond 8:47db53cd5884 27 #define SF_URLS_START_TOKEN "\"urls\":"
ansond 8:47db53cd5884 28 #define SF_URLS_STOP_TOKEN "},"
ansond 8:47db53cd5884 29
ansond 8:47db53cd5884 30 // salesforce QUERY specifier within URL
ansond 8:47db53cd5884 31 #define SF_QUERY_URL_SPECIFIER "q="
ansond 8:47db53cd5884 32
ansond 8:47db53cd5884 33 // salesforce URL API version token
ansond 8:47db53cd5884 34 #define SF_URL_API_VER_TOKEN "{version}"
ansond 8:47db53cd5884 35
ansond 17:6c774354b599 36 // HTTP response code to give for errored out conditions
ansond 17:6c774354b599 37 #define SF_GEN_ERR_HTTP_CODE 500
ansond 17:6c774354b599 38
ansond 0:518b1ca956fc 39 // include class definition
ansond 0:518b1ca956fc 40 #include "SalesforceInterface.h"
ansond 0:518b1ca956fc 41
ansond 0:518b1ca956fc 42 // Supported DataTypes for HTTPClient
ansond 0:518b1ca956fc 43 #include "HTTPMap.h"
ansond 0:518b1ca956fc 44 #include "HTTPJson.h"
ansond 0:518b1ca956fc 45
ansond 0:518b1ca956fc 46 // default constructor
ansond 0:518b1ca956fc 47 SalesforceInterface::SalesforceInterface(ErrorHandler *logger,HTTPClient *http) {
ansond 0:518b1ca956fc 48 this->m_logger = logger;
ansond 0:518b1ca956fc 49 this->m_http = http;
ansond 0:518b1ca956fc 50 this->m_username = NULL;
ansond 0:518b1ca956fc 51 this->m_password = NULL;
ansond 0:518b1ca956fc 52 this->m_client_id = NULL;
ansond 0:518b1ca956fc 53 this->m_client_secret = NULL;
ansond 0:518b1ca956fc 54 this->m_have_creds = false;
ansond 7:97ea5ef906f7 55 this->m_http_status = HTTP_OK;
ansond 7:97ea5ef906f7 56 this->m_http_response_code = -1;
ansond 7:97ea5ef906f7 57 RESET_BUFFER(this->m_http_redirection_url);
ansond 18:7dc9b949bbc3 58 RESET_SML_BUFFER(this->m_error_buffer);
ansond 8:47db53cd5884 59 memset(this->m_salesforce_api,0,SALESFORCE_API_VERSION_LENGTH);
ansond 8:47db53cd5884 60 strcpy(this->m_salesforce_api,SALESFORCE_API_VERSION);
ansond 14:3c8d11b48814 61 this->resetSalesforceToken();
ansond 0:518b1ca956fc 62 }
ansond 0:518b1ca956fc 63
ansond 0:518b1ca956fc 64 // destructor
ansond 0:518b1ca956fc 65 SalesforceInterface::~SalesforceInterface() {
ansond 0:518b1ca956fc 66 }
ansond 0:518b1ca956fc 67
ansond 0:518b1ca956fc 68 // set credentials
ansond 0:518b1ca956fc 69 void SalesforceInterface::setCredentials(char *username,char *password,char *client_id,char *client_secret) {
ansond 0:518b1ca956fc 70 this->m_username = NULL;
ansond 0:518b1ca956fc 71 this->m_password = NULL;
ansond 0:518b1ca956fc 72 this->m_client_id = NULL;
ansond 0:518b1ca956fc 73 this->m_client_secret = NULL;
ansond 0:518b1ca956fc 74 this->m_have_creds = false;
ansond 0:518b1ca956fc 75
ansond 0:518b1ca956fc 76 if (username != NULL) {
ansond 0:518b1ca956fc 77 this->m_username = username;
ansond 0:518b1ca956fc 78 if (password != NULL) {
ansond 0:518b1ca956fc 79 this->m_password = password;
ansond 0:518b1ca956fc 80 if (client_id != NULL) {
ansond 0:518b1ca956fc 81 this->m_client_id = client_id;
ansond 0:518b1ca956fc 82 if (client_secret != NULL) {
ansond 0:518b1ca956fc 83 this->m_client_secret = client_secret;
ansond 0:518b1ca956fc 84 this->m_have_creds = true;
ansond 0:518b1ca956fc 85 }
ansond 0:518b1ca956fc 86 }
ansond 0:518b1ca956fc 87 }
ansond 0:518b1ca956fc 88 }
ansond 0:518b1ca956fc 89 }
ansond 0:518b1ca956fc 90
ansond 0:518b1ca956fc 91 // convenience accessors
ansond 0:518b1ca956fc 92 ErrorHandler *SalesforceInterface::logger() { return this->m_logger; }
ansond 0:518b1ca956fc 93 HTTPClient *SalesforceInterface::http() { return this->m_http; }
ansond 7:97ea5ef906f7 94 OauthToken *SalesforceInterface::oauth() { return &this->m_oauth_token; }
ansond 0:518b1ca956fc 95 bool SalesforceInterface::haveCreds() { return this->m_have_creds; }
ansond 7:97ea5ef906f7 96 HTTPResult SalesforceInterface::httpStatus() { return this->m_http_status; }
ansond 7:97ea5ef906f7 97 int SalesforceInterface::httpResponseCode() { return this->m_http_response_code; }
ansond 8:47db53cd5884 98 void SalesforceInterface::setSalesforceAPIVersion(int version) { sprintf(this->m_salesforce_api,"%d",version); }
ansond 8:47db53cd5884 99 void SalesforceInterface::setSalesforceAPIVersion(char *version) { if (version != NULL && strlen(version) > 0 && strlen(version) < SALESFORCE_API_VERSION_LENGTH) strcpy(this->m_salesforce_api,version); }
ansond 8:47db53cd5884 100 char *SalesforceInterface::getSalesforceAPIVersion() { return this->m_salesforce_api; }
ansond 7:97ea5ef906f7 101
ansond 7:97ea5ef906f7 102 // reset our oauth token
ansond 7:97ea5ef906f7 103 void SalesforceInterface::resetOauthToken() {
ansond 9:a254fcd904be 104 DEBUG("resetting OAUTH token...");
ansond 7:97ea5ef906f7 105 this->m_oauth_token.valid = false;
ansond 7:97ea5ef906f7 106 this->m_oauth_token.id = "";
ansond 7:97ea5ef906f7 107 this->m_oauth_token.issued_at = "";
ansond 7:97ea5ef906f7 108 this->m_oauth_token.token_type = "";
ansond 7:97ea5ef906f7 109 this->m_oauth_token.instance_url = "";
ansond 7:97ea5ef906f7 110 this->m_oauth_token.signature = "";
ansond 7:97ea5ef906f7 111 this->m_oauth_token.access_token = "";
ansond 9:a254fcd904be 112 if (this->http() != NULL) this->http()->oauthToken(NULL);
ansond 7:97ea5ef906f7 113 }
ansond 7:97ea5ef906f7 114
ansond 7:97ea5ef906f7 115 // fill our oauth token
ansond 7:97ea5ef906f7 116 void SalesforceInterface::fillOauthToken(char *token) {
ansond 7:97ea5ef906f7 117 if (token != NULL && strlen(token) > 0) {
ansond 7:97ea5ef906f7 118 // parse JSON
ansond 7:97ea5ef906f7 119 MbedJSONValue parsed_token;
ansond 7:97ea5ef906f7 120 parse(parsed_token,token);
ansond 7:97ea5ef906f7 121
ansond 7:97ea5ef906f7 122 // fill our OAUTH token
ansond 7:97ea5ef906f7 123 this->m_oauth_token.id = parsed_token["id"].get<std::string>();
ansond 7:97ea5ef906f7 124 this->m_oauth_token.issued_at = parsed_token["issued_at"].get<std::string>();
ansond 7:97ea5ef906f7 125 this->m_oauth_token.token_type = parsed_token["token_type"].get<std::string>();
ansond 7:97ea5ef906f7 126 this->m_oauth_token.instance_url = parsed_token["instance_url"].get<std::string>();
ansond 7:97ea5ef906f7 127 this->m_oauth_token.signature = parsed_token["signature"].get<std::string>();
ansond 7:97ea5ef906f7 128 this->m_oauth_token.access_token = parsed_token["access_token"].get<std::string>();
ansond 7:97ea5ef906f7 129
ansond 7:97ea5ef906f7 130 // we have an OAUTH token now
ansond 7:97ea5ef906f7 131 this->m_oauth_token.valid = true;
ansond 7:97ea5ef906f7 132 DEBUG("valid OAUTH token acquired.");
ansond 7:97ea5ef906f7 133 return;
ansond 7:97ea5ef906f7 134 }
ansond 7:97ea5ef906f7 135 DEBUG("error: invalid or null OAUTH token fill attempt.");
ansond 7:97ea5ef906f7 136 }
ansond 7:97ea5ef906f7 137
ansond 7:97ea5ef906f7 138 // is our OAUTH token valid?
ansond 9:a254fcd904be 139 bool SalesforceInterface::validOauthToken(bool fetch) {
ansond 7:97ea5ef906f7 140 // make sure we have a valid OAUTH Token
ansond 9:a254fcd904be 141 this->checkAndGetOauthToken(fetch);
ansond 7:97ea5ef906f7 142 return this->m_oauth_token.valid;
ansond 8:47db53cd5884 143 }
ansond 9:a254fcd904be 144
ansond 15:89044c68ad36 145 // reset our salesforce token and OAUTH tokens
ansond 14:3c8d11b48814 146 void SalesforceInterface::resetSalesforceToken() {
ansond 9:a254fcd904be 147 this->resetOauthToken();
ansond 9:a254fcd904be 148 RESET_BUFFER(this->m_salesforce_id);
ansond 9:a254fcd904be 149 }
ansond 8:47db53cd5884 150
ansond 15:89044c68ad36 151 // do we have a valid salesforce.com token?
ansond 14:3c8d11b48814 152 bool SalesforceInterface::haveSalesforceToken(bool fetch) {
ansond 8:47db53cd5884 153 if (this->m_salesforce_id != NULL && strlen(this->m_salesforce_id) > 0) return true;
ansond 9:a254fcd904be 154 if (fetch) {
ansond 14:3c8d11b48814 155 this->logger()->log("No Salesforce Token found... fetching...");
ansond 14:3c8d11b48814 156 this->getSalesforceToken();
ansond 14:3c8d11b48814 157 return this->haveSalesforceToken(false);
ansond 9:a254fcd904be 158 }
ansond 8:47db53cd5884 159 return false;
ansond 8:47db53cd5884 160 }
ansond 7:97ea5ef906f7 161
ansond 7:97ea5ef906f7 162 // check and get our OAUTH token
ansond 9:a254fcd904be 163 void SalesforceInterface::checkAndGetOauthToken(bool fetch) {
ansond 7:97ea5ef906f7 164 DEBUG("checking for valid OAUTH token...");
ansond 9:a254fcd904be 165
ansond 9:a254fcd904be 166 // reset the token structure for sanity...
ansond 9:a254fcd904be 167 if (this->m_oauth_token.valid == false) this->resetOauthToken();
ansond 9:a254fcd904be 168
ansond 9:a254fcd904be 169 // should go fetch our token if we dont have one?
ansond 9:a254fcd904be 170 // just pass through if we already have a token
ansond 9:a254fcd904be 171 if (this->m_oauth_token.valid == true) {
ansond 9:a254fcd904be 172 DEBUG("valid OAUTH token found.");
ansond 9:a254fcd904be 173 }
ansond 9:a254fcd904be 174 else if (this->m_oauth_token.valid == false && fetch == true) {
ansond 9:a254fcd904be 175 // get our OAUTH token
ansond 9:a254fcd904be 176 DEBUG("No OAUTH token found. Acquiring OAUTH token...");
ansond 7:97ea5ef906f7 177 ALLOC_BUFFER(output_buffer);
ansond 7:97ea5ef906f7 178 char *token = this->getOauthToken(output_buffer,MAX_BUFFER_LENGTH);
ansond 9:a254fcd904be 179 if (token != NULL && strlen(token) > 0) {
ansond 9:a254fcd904be 180 // fill
ansond 9:a254fcd904be 181 DEBUG("Saving OAUTH token...");
ansond 9:a254fcd904be 182 this->fillOauthToken(token);
ansond 9:a254fcd904be 183 return;
ansond 9:a254fcd904be 184 }
ansond 9:a254fcd904be 185 else {
ansond 9:a254fcd904be 186 // unable to get the token (reset for sanity)
ansond 9:a254fcd904be 187 this->logger()->log("error in acquiring OAUTH token http_code=%d status=%d",this->httpResponseCode(),this->httpStatus());
ansond 9:a254fcd904be 188 this->resetOauthToken();
ansond 9:a254fcd904be 189 }
ansond 7:97ea5ef906f7 190 }
ansond 9:a254fcd904be 191
ansond 9:a254fcd904be 192 // else report that we dont have a token
ansond 9:a254fcd904be 193 else {
ansond 9:a254fcd904be 194 this->logger()->log("No OAUTH token found (fetch=false).");
ansond 9:a254fcd904be 195 }
ansond 9:a254fcd904be 196 }
ansond 0:518b1ca956fc 197
ansond 0:518b1ca956fc 198 //
ansond 0:518b1ca956fc 199 // get OAUTH2 Token - taken from here:
ansond 0:518b1ca956fc 200 // https://developer.salesforce.com/page/Digging_Deeper_into_OAuth_2.0_on_Force.com#Obtaining_a_Token_in_an_Autonomous_Client_.28Username_and_Password_Flow.29
ansond 0:518b1ca956fc 201 //
ansond 0:518b1ca956fc 202 char *SalesforceInterface::getOauthToken(char *output_buffer,int output_buffer_length) {
ansond 1:a7dca096e47d 203 if (this->haveCreds()) {
ansond 0:518b1ca956fc 204 // construct the OAUTH2 Token request body
ansond 0:518b1ca956fc 205 HTTPMap input;
ansond 0:518b1ca956fc 206
ansond 0:518b1ca956fc 207 //
ansond 0:518b1ca956fc 208 // FORMAT: Taken from URL above method signature:
ansond 0:518b1ca956fc 209 //
ansond 0:518b1ca956fc 210 // grant_type=password&client_id=<your_client_id>&client_secret=<your_client_secret>&username=<your_username>&password=<your_password>
ansond 0:518b1ca956fc 211 //
ansond 0:518b1ca956fc 212 // ContentType: application/x-www-form-urlencoded
ansond 0:518b1ca956fc 213 //
ansond 0:518b1ca956fc 214 input.put("grant_type","password");
ansond 0:518b1ca956fc 215 input.put("client_id",this->m_client_id);
ansond 0:518b1ca956fc 216 input.put("client_secret",this->m_client_secret);
ansond 0:518b1ca956fc 217 input.put("username",this->m_username);
ansond 0:518b1ca956fc 218 input.put("password",this->m_password);
ansond 1:a7dca096e47d 219
ansond 0:518b1ca956fc 220 // prepare the output buffer
ansond 0:518b1ca956fc 221 HTTPText output(output_buffer,output_buffer_length);
ansond 0:518b1ca956fc 222
ansond 0:518b1ca956fc 223 // HTTP POST call to gett he token
ansond 7:97ea5ef906f7 224 DEBUG("Getting OAUTH Token...");
ansond 7:97ea5ef906f7 225 this->m_http_status = this->http()->post(SF_OAUTH_TOKEN_URL,input,&output);
ansond 7:97ea5ef906f7 226
ansond 0:518b1ca956fc 227 // check the result and return the token
ansond 9:a254fcd904be 228 if (this->httpStatus() == HTTP_OK || this->httpResponseCode() == 200) return output_buffer;
ansond 9:a254fcd904be 229 this->logger()->log("acquire oauth FAILED. URL: %s http_code=%d status=%d",SF_OAUTH_TOKEN_URL,this->httpResponseCode(),this->httpStatus());
ansond 0:518b1ca956fc 230 }
ansond 0:518b1ca956fc 231 else {
ansond 0:518b1ca956fc 232 // no credentials
ansond 0:518b1ca956fc 233 this->logger()->log("no/incomplete salesforce.com credentials provided. Unable to acquire OAUTH2 token...");
ansond 0:518b1ca956fc 234 }
ansond 0:518b1ca956fc 235 return NULL;
ansond 0:518b1ca956fc 236 }
ansond 0:518b1ca956fc 237
ansond 15:89044c68ad36 238 // Salesforce.com: Get our token
ansond 14:3c8d11b48814 239 char *SalesforceInterface::getSalesforceToken(bool fetch) {
ansond 7:97ea5ef906f7 240 // proceed only if we have a valid OAUTH Token
ansond 9:a254fcd904be 241 if (this->validOauthToken(fetch) == true) {
ansond 15:89044c68ad36 242 // pull the token from salesforce
ansond 8:47db53cd5884 243 RESET_BUFFER(this->m_salesforce_id);
ansond 8:47db53cd5884 244 char *id = this->invoke(this->oauth()->id.c_str(),this->m_salesforce_id,MAX_BUFFER_LENGTH);
ansond 7:97ea5ef906f7 245
ansond 7:97ea5ef906f7 246 // log any error status and return what we have...
ansond 14:3c8d11b48814 247 if (this->httpStatus() != HTTP_OK) this->logger()->log("Unable to get Salesforce Token: status=%d httpCode=%d",this->httpStatus(),this->httpResponseCode());
ansond 7:97ea5ef906f7 248 return id;
ansond 7:97ea5ef906f7 249 }
ansond 7:97ea5ef906f7 250 else {
ansond 15:89044c68ad36 251 // unable to get token - no OAUTH token
ansond 14:3c8d11b48814 252 this->logger()->log("Unable to get Salesforce Token: no valid OAUTH token.");
ansond 7:97ea5ef906f7 253 }
ansond 7:97ea5ef906f7 254 return NULL;
ansond 7:97ea5ef906f7 255 }
ansond 7:97ea5ef906f7 256
ansond 8:47db53cd5884 257 // QUERY: Salesforce.com
ansond 8:47db53cd5884 258 char *SalesforceInterface::query(char *query_str,char *output_buffer,int output_buffer_length) {
ansond 15:89044c68ad36 259 // first we have to ensure that we have valid salesforce token
ansond 14:3c8d11b48814 260 if (this->haveSalesforceToken()) {
ansond 9:a254fcd904be 261 // get the query url
ansond 8:47db53cd5884 262 ALLOC_BUFFER(url);
ansond 8:47db53cd5884 263 char *sf_url = this->getSalesforceURL("query",url,MAX_BUFFER_LENGTH);
ansond 8:47db53cd5884 264 if (sf_url != NULL && strlen(sf_url) > 0) {
ansond 8:47db53cd5884 265 // make sure that the query string is ready to ship...
ansond 8:47db53cd5884 266 ALLOC_SML_BUFFER(tmp_query);
ansond 8:47db53cd5884 267
ansond 8:47db53cd5884 268 // replace all spaces in query with "+"
ansond 8:47db53cd5884 269 strcpy(tmp_query,query_str);
ansond 8:47db53cd5884 270 this->replace(tmp_query,' ','+'); // will modify tmp_query directly...
ansond 8:47db53cd5884 271
ansond 8:47db53cd5884 272 // customize the URL with our (formatted) query string
ansond 8:47db53cd5884 273 string str_url(sf_url);
ansond 8:47db53cd5884 274 str_url[str_url.length()-1] = '?'; // remove the slash and add a ?
ansond 8:47db53cd5884 275 str_url = str_url + SF_QUERY_URL_SPECIFIER + tmp_query; // add the query specifier
ansond 8:47db53cd5884 276
ansond 8:47db53cd5884 277 // DEBUG - show the query URL
ansond 8:47db53cd5884 278 DEBUG("query URL: %s",str_url.c_str());
ansond 8:47db53cd5884 279
ansond 8:47db53cd5884 280 // invoke with GET
ansond 8:47db53cd5884 281 return this->invoke((const char *)str_url.c_str(),output_buffer,output_buffer_length);
ansond 8:47db53cd5884 282 }
ansond 8:47db53cd5884 283 else {
ansond 8:47db53cd5884 284 // unable to find the query URL...
ansond 15:89044c68ad36 285 this->logger()->log("query: error - unable to find query URL in salesforce token...");
ansond 8:47db53cd5884 286 }
ansond 8:47db53cd5884 287 }
ansond 8:47db53cd5884 288 else {
ansond 15:89044c68ad36 289 // dont have a valid salesforce token
ansond 19:6a791e5449b3 290 this->logger()->log("query: error - no valid salesforce token was found...");
ansond 8:47db53cd5884 291 }
ansond 8:47db53cd5884 292 return NULL;
ansond 8:47db53cd5884 293 }
ansond 8:47db53cd5884 294
ansond 14:3c8d11b48814 295 // CREATE: a record in Salesforce.com
ansond 14:3c8d11b48814 296 MbedJSONValue SalesforceInterface::createRecord(char *object_name,MbedJSONValue &record) {
ansond 9:a254fcd904be 297 ALLOC_BUFFER(output_buffer);
ansond 14:3c8d11b48814 298 char *reply = this->createRecord(object_name,(char *)record.serialize().c_str(),output_buffer,MAX_BUFFER_LENGTH);
ansond 9:a254fcd904be 299 MbedJSONValue response;
ansond 9:a254fcd904be 300 if (reply != NULL && strlen(reply) > 0) parse(response,reply);
ansond 9:a254fcd904be 301 return response;
ansond 9:a254fcd904be 302 }
ansond 9:a254fcd904be 303
ansond 14:3c8d11b48814 304 // READ: a specific record in Salesforce.com
ansond 16:3d160f224084 305 MbedJSONValue SalesforceInterface::readRecord(char *object_name,char *record_id,char *record_value) {
ansond 9:a254fcd904be 306 ALLOC_BUFFER(output_buffer);
ansond 16:3d160f224084 307 char *reply = this->readRecord(object_name,record_id,record_value,output_buffer,MAX_BUFFER_LENGTH);
ansond 9:a254fcd904be 308 MbedJSONValue response;
ansond 9:a254fcd904be 309 if (reply != NULL && strlen(reply) > 0) parse(response,reply);
ansond 9:a254fcd904be 310 return response;
ansond 9:a254fcd904be 311 }
ansond 9:a254fcd904be 312
ansond 14:3c8d11b48814 313 // UPDATE: a specific record in Salesforce.com
ansond 14:3c8d11b48814 314 bool SalesforceInterface::updateRecord(char *object_name,char *record_id,MbedJSONValue &record) {
ansond 18:7dc9b949bbc3 315 RESET_SML_BUFFER(this->m_error_buffer);
ansond 18:7dc9b949bbc3 316 return this->updateRecord(object_name,record_id,(char *)record.serialize().c_str(),this->m_error_buffer,MAX_SMALL_BUFFER_LENGTH);
ansond 9:a254fcd904be 317 }
ansond 9:a254fcd904be 318
ansond 16:3d160f224084 319 // UPSERT: update/insert an External ID record in Salesforce.com
ansond 16:3d160f224084 320 bool SalesforceInterface::upsertRecord(char *object_name,char *external_id_field_name,char *external_id_field_value,MbedJSONValue &record) {
ansond 18:7dc9b949bbc3 321 RESET_SML_BUFFER(this->m_error_buffer);
ansond 18:7dc9b949bbc3 322 return this->upsertRecord(object_name,external_id_field_name,external_id_field_value,(char *)record.serialize().c_str(),this->m_error_buffer,MAX_SMALL_BUFFER_LENGTH);
ansond 18:7dc9b949bbc3 323 }
ansond 18:7dc9b949bbc3 324
ansond 18:7dc9b949bbc3 325 // DELETE: a specific record in Salesforce.com
ansond 18:7dc9b949bbc3 326 bool SalesforceInterface::deleteRecord(char *object_name,char *record_id) {
ansond 18:7dc9b949bbc3 327 RESET_SML_BUFFER(this->m_error_buffer);
ansond 18:7dc9b949bbc3 328 return this->deleteRecord(object_name,record_id,this->m_error_buffer,MAX_SMALL_BUFFER_LENGTH);
ansond 18:7dc9b949bbc3 329 }
ansond 18:7dc9b949bbc3 330
ansond 18:7dc9b949bbc3 331 // ERROR: get last error result
ansond 18:7dc9b949bbc3 332 MbedJSONValue SalesforceInterface::getLastError() {
ansond 18:7dc9b949bbc3 333 MbedJSONValue error;
ansond 18:7dc9b949bbc3 334 if (strlen(this->m_error_buffer) > 0) parse(error,this->m_error_buffer);
ansond 18:7dc9b949bbc3 335 return error;
ansond 16:3d160f224084 336 }
ansond 16:3d160f224084 337
ansond 14:3c8d11b48814 338 // CREATE: a record in Salesforce.com
ansond 14:3c8d11b48814 339 char *SalesforceInterface::createRecord(char *object_name,char *json_data,char *output_buffer,int output_buffer_length) {
ansond 9:a254fcd904be 340 // parameter check
ansond 9:a254fcd904be 341 if (object_name != NULL && strlen(object_name) > 0 && json_data != NULL && strlen(json_data) > 0 && output_buffer != NULL && output_buffer_length > 0) {
ansond 15:89044c68ad36 342 // first we have to ensure that we have valid salesforce token
ansond 14:3c8d11b48814 343 if (this->haveSalesforceToken()) {
ansond 9:a254fcd904be 344 // get the sobjects url
ansond 9:a254fcd904be 345 ALLOC_BUFFER(url);
ansond 9:a254fcd904be 346 char *sf_url = this->getSalesforceURL("sobjects",url,MAX_BUFFER_LENGTH);
ansond 9:a254fcd904be 347 if (sf_url != NULL && strlen(sf_url) > 0) {
ansond 9:a254fcd904be 348 // convert to string
ansond 9:a254fcd904be 349 string str_url(sf_url);
ansond 9:a254fcd904be 350
ansond 14:3c8d11b48814 351 // add object name that we want to create a record in
ansond 9:a254fcd904be 352 str_url += object_name;
ansond 9:a254fcd904be 353
ansond 9:a254fcd904be 354 // DEBUG
ansond 14:3c8d11b48814 355 DEBUG("createRecord: URL: %s DATA: %s",str_url.c_str(),json_data);
ansond 9:a254fcd904be 356
ansond 9:a254fcd904be 357 // now invoke with POST with JSON data type
ansond 9:a254fcd904be 358 return this->invoke(str_url.c_str(),json_data,strlen(json_data)+1,output_buffer,output_buffer_length);
ansond 9:a254fcd904be 359 }
ansond 9:a254fcd904be 360 }
ansond 9:a254fcd904be 361 else {
ansond 15:89044c68ad36 362 // dont have a valid salesforce token
ansond 19:6a791e5449b3 363 this->logger()->log("createRecord: error - no valid salesforce token was found...");
ansond 9:a254fcd904be 364 }
ansond 9:a254fcd904be 365 }
ansond 9:a254fcd904be 366 else {
ansond 9:a254fcd904be 367 // invalid or NULL parameters
ansond 14:3c8d11b48814 368 this->logger()->log("createRecord: error - invalid or NULL parameters...");
ansond 9:a254fcd904be 369 }
ansond 17:6c774354b599 370 this->m_http_response_code = SF_GEN_ERR_HTTP_CODE;
ansond 9:a254fcd904be 371 return NULL;
ansond 9:a254fcd904be 372 }
ansond 9:a254fcd904be 373
ansond 14:3c8d11b48814 374 // READ: a specific record in Salesforce.com
ansond 16:3d160f224084 375 char *SalesforceInterface::readRecord(char *object_name,char *record_id,char *record_value,char *output_buffer,int output_buffer_length) {
ansond 9:a254fcd904be 376 // parameter check
ansond 14:3c8d11b48814 377 if (object_name != NULL && strlen(object_name) > 0 && record_id != NULL && strlen(record_id) > 0 && output_buffer != NULL && output_buffer_length > 0) {
ansond 15:89044c68ad36 378 // first we have to ensure that we have valid salesforce token
ansond 14:3c8d11b48814 379 if (this->haveSalesforceToken()) {
ansond 9:a254fcd904be 380 // get the sobjects url
ansond 9:a254fcd904be 381 ALLOC_BUFFER(url);
ansond 9:a254fcd904be 382 char *sf_url = this->getSalesforceURL("sobjects",url,MAX_BUFFER_LENGTH);
ansond 9:a254fcd904be 383 if (sf_url != NULL && strlen(sf_url) > 0) {
ansond 9:a254fcd904be 384 // convert to string
ansond 9:a254fcd904be 385 string str_url(sf_url);
ansond 9:a254fcd904be 386
ansond 14:3c8d11b48814 387 // add object name that we want to create a record in
ansond 9:a254fcd904be 388 str_url += object_name;
ansond 9:a254fcd904be 389
ansond 15:89044c68ad36 390 // add the record token
ansond 9:a254fcd904be 391 str_url += "/";
ansond 14:3c8d11b48814 392 str_url += record_id;
ansond 9:a254fcd904be 393
ansond 16:3d160f224084 394 // add the record value (if present)
ansond 16:3d160f224084 395 if (record_value != NULL && strlen(record_value) > 0) {
ansond 16:3d160f224084 396 str_url += "/";
ansond 16:3d160f224084 397 str_url += record_value;
ansond 16:3d160f224084 398 }
ansond 16:3d160f224084 399
ansond 9:a254fcd904be 400 // DEBUG
ansond 14:3c8d11b48814 401 DEBUG("readRecord: URL: %s",str_url.c_str());
ansond 9:a254fcd904be 402
ansond 9:a254fcd904be 403 // now invoke with GET with JSON data type
ansond 9:a254fcd904be 404 return this->invoke(str_url.c_str(),output_buffer,output_buffer_length);
ansond 9:a254fcd904be 405 }
ansond 9:a254fcd904be 406 }
ansond 9:a254fcd904be 407 else {
ansond 15:89044c68ad36 408 // dont have a valid salesforce token
ansond 19:6a791e5449b3 409 this->logger()->log("readRecord: error - no valid salesforce token was found...");
ansond 9:a254fcd904be 410 }
ansond 9:a254fcd904be 411 }
ansond 9:a254fcd904be 412 else {
ansond 9:a254fcd904be 413 // invalid or NULL parameters
ansond 14:3c8d11b48814 414 this->logger()->log("readRecord: error - invalid or NULL parameters...");
ansond 9:a254fcd904be 415 }
ansond 17:6c774354b599 416 this->m_http_response_code = SF_GEN_ERR_HTTP_CODE;
ansond 9:a254fcd904be 417 return NULL;
ansond 9:a254fcd904be 418 }
ansond 9:a254fcd904be 419
ansond 14:3c8d11b48814 420 // UPDATE: a specific record in Salesforce.com
ansond 20:0d6abaf6d7c5 421 bool SalesforceInterface::updateRecord(char *object_name,char *record_id,char *json_data,char *output_buffer,int output_buffer_length) {
ansond 20:0d6abaf6d7c5 422 // reset the error buffer
ansond 20:0d6abaf6d7c5 423 RESET_SML_BUFFER(this->m_error_buffer);
ansond 20:0d6abaf6d7c5 424
ansond 9:a254fcd904be 425 // parameter check
ansond 9:a254fcd904be 426 if (object_name != NULL && strlen(object_name) > 0 && json_data != NULL && strlen(json_data) > 0) {
ansond 15:89044c68ad36 427 // first we have to ensure that we have valid salesforce token
ansond 14:3c8d11b48814 428 if (this->haveSalesforceToken()) {
ansond 9:a254fcd904be 429 // get the sobjects url
ansond 9:a254fcd904be 430 ALLOC_BUFFER(url);
ansond 9:a254fcd904be 431 char *sf_url = this->getSalesforceURL("sobjects",url,MAX_BUFFER_LENGTH);
ansond 9:a254fcd904be 432 if (sf_url != NULL && strlen(sf_url) > 0) {
ansond 9:a254fcd904be 433 // convert to string
ansond 9:a254fcd904be 434 string str_url(sf_url);
ansond 9:a254fcd904be 435
ansond 14:3c8d11b48814 436 // add object name that we want to create a record in
ansond 9:a254fcd904be 437 str_url += object_name;
ansond 9:a254fcd904be 438
ansond 15:89044c68ad36 439 // add the record token
ansond 9:a254fcd904be 440 str_url += "/";
ansond 14:3c8d11b48814 441 str_url += record_id;
ansond 9:a254fcd904be 442
ansond 9:a254fcd904be 443 // HTTPClient does not support PATCH, so we have to use POST with a special added parameter
ansond 9:a254fcd904be 444 str_url += "?_HttpMethod=PATCH";
ansond 9:a254fcd904be 445
ansond 9:a254fcd904be 446 // DEBUG
ansond 14:3c8d11b48814 447 DEBUG("updateRecord: URL: %s DATA: %s",str_url.c_str(),json_data);
ansond 9:a254fcd904be 448
ansond 9:a254fcd904be 449 // now invoke with POST with JSON data type
ansond 18:7dc9b949bbc3 450 char *reply = this->invoke(str_url.c_str(),json_data,strlen(json_data)+1,output_buffer,output_buffer_length);
ansond 9:a254fcd904be 451
ansond 9:a254fcd904be 452 // DEBUG
ansond 14:3c8d11b48814 453 DEBUG("updateRecord: http status=%d",this->httpResponseCode());
ansond 9:a254fcd904be 454
ansond 9:a254fcd904be 455 // return our status
ansond 17:6c774354b599 456 if (this->httpResponseCodeInRange(200)) return true;
ansond 20:0d6abaf6d7c5 457
ansond 20:0d6abaf6d7c5 458 // we are in error - so copy the result if we have one and return false
ansond 20:0d6abaf6d7c5 459 if (reply != NULL && strlen(reply) > 0) strncpy(this->m_error_buffer,reply,this->min(strlen(reply),MAX_SMALL_BUFFER_LENGTH));
ansond 9:a254fcd904be 460 return false;
ansond 9:a254fcd904be 461 }
ansond 9:a254fcd904be 462 }
ansond 9:a254fcd904be 463 else {
ansond 15:89044c68ad36 464 // dont have a valid salesforce token
ansond 19:6a791e5449b3 465 this->logger()->log("updateRecord: error - no valid salesforce token was found...");
ansond 9:a254fcd904be 466 }
ansond 9:a254fcd904be 467 }
ansond 9:a254fcd904be 468 else {
ansond 9:a254fcd904be 469 // invalid or NULL parameters
ansond 14:3c8d11b48814 470 this->logger()->log("updateRecord: error - invalid or NULL parameters...");
ansond 9:a254fcd904be 471 }
ansond 17:6c774354b599 472 this->m_http_response_code = SF_GEN_ERR_HTTP_CODE;
ansond 9:a254fcd904be 473 return false;
ansond 9:a254fcd904be 474 }
ansond 16:3d160f224084 475
ansond 16:3d160f224084 476 // UPSERT: update/insert a specific External record in Salesforce.com
ansond 18:7dc9b949bbc3 477 bool SalesforceInterface::upsertRecord(char *object_name,char *external_id_field_name,char *external_id_field_value,char *json_data,char *output_buffer,int output_buffer_length) {
ansond 20:0d6abaf6d7c5 478 // reset the error buffer
ansond 20:0d6abaf6d7c5 479 RESET_SML_BUFFER(this->m_error_buffer);
ansond 20:0d6abaf6d7c5 480
ansond 16:3d160f224084 481 // parameter check
ansond 16:3d160f224084 482 if (object_name != NULL && strlen(object_name) > 0 && json_data != NULL && strlen(json_data) > 0) {
ansond 16:3d160f224084 483 // first we have to ensure that we have valid salesforce token
ansond 16:3d160f224084 484 if (this->haveSalesforceToken()) {
ansond 16:3d160f224084 485 // get the sobjects url
ansond 16:3d160f224084 486 ALLOC_BUFFER(url);
ansond 16:3d160f224084 487 char *sf_url = this->getSalesforceURL("sobjects",url,MAX_BUFFER_LENGTH);
ansond 16:3d160f224084 488 if (sf_url != NULL && strlen(sf_url) > 0) {
ansond 16:3d160f224084 489 // convert to string
ansond 16:3d160f224084 490 string str_url(sf_url);
ansond 16:3d160f224084 491
ansond 16:3d160f224084 492 // add object name that we want to create a record in
ansond 16:3d160f224084 493 str_url += object_name;
ansond 16:3d160f224084 494
ansond 16:3d160f224084 495 // add the external field name token
ansond 16:3d160f224084 496 str_url += "/";
ansond 16:3d160f224084 497 str_url += external_id_field_name;
ansond 16:3d160f224084 498
ansond 16:3d160f224084 499 // add the external field value token (if not NULL)
ansond 16:3d160f224084 500 if (external_id_field_value != NULL && strlen(external_id_field_value) > 0) {
ansond 16:3d160f224084 501 str_url += "/";
ansond 16:3d160f224084 502 str_url += external_id_field_value;
ansond 16:3d160f224084 503 }
ansond 16:3d160f224084 504
ansond 16:3d160f224084 505 // HTTPClient does not support PATCH, so we have to use POST with a special added parameter
ansond 16:3d160f224084 506 str_url += "?_HttpMethod=PATCH";
ansond 16:3d160f224084 507
ansond 16:3d160f224084 508 // DEBUG
ansond 16:3d160f224084 509 DEBUG("upsertRecord: URL: %s DATA: %s",str_url.c_str(),json_data);
ansond 16:3d160f224084 510
ansond 16:3d160f224084 511 // now invoke with POST with JSON data type
ansond 18:7dc9b949bbc3 512 char *reply = this->invoke(str_url.c_str(),json_data,strlen(json_data)+1,output_buffer,output_buffer_length);
ansond 16:3d160f224084 513
ansond 16:3d160f224084 514 // DEBUG
ansond 16:3d160f224084 515 DEBUG("upsertRecord: http status=%d",this->httpResponseCode());
ansond 16:3d160f224084 516
ansond 16:3d160f224084 517 // return our status
ansond 17:6c774354b599 518 if (this->httpResponseCodeInRange(200)) return true;
ansond 20:0d6abaf6d7c5 519
ansond 20:0d6abaf6d7c5 520 // we are in error - so copy the result if we have one and return false
ansond 20:0d6abaf6d7c5 521 if (reply != NULL && strlen(reply) > 0) strncpy(this->m_error_buffer,reply,this->min(strlen(reply),MAX_SMALL_BUFFER_LENGTH));
ansond 16:3d160f224084 522 return false;
ansond 16:3d160f224084 523 }
ansond 16:3d160f224084 524 }
ansond 16:3d160f224084 525 else {
ansond 16:3d160f224084 526 // dont have a valid salesforce token
ansond 19:6a791e5449b3 527 this->logger()->log("upsertRecord: error - no valid salesforce token was found...");
ansond 16:3d160f224084 528 }
ansond 16:3d160f224084 529 }
ansond 16:3d160f224084 530 else {
ansond 16:3d160f224084 531 // invalid or NULL parameters
ansond 16:3d160f224084 532 this->logger()->log("upsertRecord: error - invalid or NULL parameters...");
ansond 16:3d160f224084 533 }
ansond 17:6c774354b599 534 this->m_http_response_code = SF_GEN_ERR_HTTP_CODE;
ansond 16:3d160f224084 535 return false;
ansond 16:3d160f224084 536 }
ansond 9:a254fcd904be 537
ansond 14:3c8d11b48814 538 // DELETE: a specific record in Salesforce.com
ansond 18:7dc9b949bbc3 539 bool SalesforceInterface::deleteRecord(char *object_name,char *record_id,char *output_buffer,int output_buffer_length) {
ansond 20:0d6abaf6d7c5 540 // reset the error buffer
ansond 20:0d6abaf6d7c5 541 RESET_SML_BUFFER(this->m_error_buffer);
ansond 20:0d6abaf6d7c5 542
ansond 9:a254fcd904be 543 // parameter check
ansond 14:3c8d11b48814 544 if (object_name != NULL && strlen(object_name) > 0 && record_id != NULL && strlen(record_id) > 0) {
ansond 15:89044c68ad36 545 // first we have to ensure that we have valid salesforce token
ansond 14:3c8d11b48814 546 if (this->haveSalesforceToken()) {
ansond 9:a254fcd904be 547 // get the sobjects url
ansond 9:a254fcd904be 548 ALLOC_BUFFER(url);
ansond 9:a254fcd904be 549 char *sf_url = this->getSalesforceURL("sobjects",url,MAX_BUFFER_LENGTH);
ansond 9:a254fcd904be 550 if (sf_url != NULL && strlen(sf_url) > 0) {
ansond 9:a254fcd904be 551 // convert to string
ansond 9:a254fcd904be 552 string str_url(sf_url);
ansond 9:a254fcd904be 553
ansond 14:3c8d11b48814 554 // add object name that we want to create a record in
ansond 9:a254fcd904be 555 str_url += object_name;
ansond 9:a254fcd904be 556
ansond 15:89044c68ad36 557 // add the record token
ansond 9:a254fcd904be 558 str_url += "/";
ansond 14:3c8d11b48814 559 str_url += record_id;
ansond 9:a254fcd904be 560
ansond 9:a254fcd904be 561 // DEBUG
ansond 14:3c8d11b48814 562 DEBUG("deleteRecord: URL: %s",str_url.c_str());
ansond 9:a254fcd904be 563
ansond 9:a254fcd904be 564 // now invoke with DELETE
ansond 9:a254fcd904be 565 ALLOC_SML_BUFFER(output_buffer);
ansond 18:7dc9b949bbc3 566 char *reply = this->invoke(str_url.c_str(),output_buffer,output_buffer_length,DELETE);
ansond 9:a254fcd904be 567
ansond 9:a254fcd904be 568 // DEBUG
ansond 14:3c8d11b48814 569 DEBUG("deleteRecord: http status=%d",this->httpResponseCode());
ansond 9:a254fcd904be 570
ansond 9:a254fcd904be 571 // return our status
ansond 17:6c774354b599 572 if (this->httpResponseCodeInRange(200)) return true;
ansond 20:0d6abaf6d7c5 573
ansond 20:0d6abaf6d7c5 574 // we are in error - so copy the result if we have one and return false
ansond 20:0d6abaf6d7c5 575 if (reply != NULL && strlen(reply) > 0) strncpy(this->m_error_buffer,reply,this->min(strlen(reply),MAX_SMALL_BUFFER_LENGTH));
ansond 9:a254fcd904be 576 return false;
ansond 9:a254fcd904be 577 }
ansond 9:a254fcd904be 578 }
ansond 9:a254fcd904be 579 else {
ansond 15:89044c68ad36 580 // dont have a valid salesforce token
ansond 19:6a791e5449b3 581 this->logger()->log("deleteRecord: error - no valid salesforce token was found...");
ansond 9:a254fcd904be 582 }
ansond 9:a254fcd904be 583 }
ansond 9:a254fcd904be 584 else {
ansond 9:a254fcd904be 585 // invalid or NULL parameters
ansond 14:3c8d11b48814 586 this->logger()->log("deleteRecord: error - invalid or NULL parameters...");
ansond 9:a254fcd904be 587 }
ansond 17:6c774354b599 588 this->m_http_response_code = SF_GEN_ERR_HTTP_CODE;
ansond 9:a254fcd904be 589 return false;
ansond 9:a254fcd904be 590 }
ansond 9:a254fcd904be 591
ansond 0:518b1ca956fc 592 // Salesforce.com Invoke: defaults to GET
ansond 9:a254fcd904be 593 char *SalesforceInterface::invoke(const char *url,char *output_buffer,int output_buffer_length) {
ansond 9:a254fcd904be 594 return this->invoke(url,output_buffer,output_buffer_length,GET);
ansond 9:a254fcd904be 595 }
ansond 9:a254fcd904be 596
ansond 9:a254fcd904be 597 // Salesforce.com Invoke: GET or DELETE with simple output
ansond 9:a254fcd904be 598 char *SalesforceInterface::invoke(const char *url,char *output_buffer,int output_buffer_length,HttpVerb verb) {
ansond 9:a254fcd904be 599 char *response = NULL;
ansond 9:a254fcd904be 600 switch(verb) {
ansond 9:a254fcd904be 601 case GET:
ansond 9:a254fcd904be 602 case DELETE:
ansond 9:a254fcd904be 603 // GET and DELETE only require an output buffer...
ansond 9:a254fcd904be 604 response = this->invoke(url,NUM_TYPES,NULL,0,output_buffer,output_buffer_length,verb);
ansond 9:a254fcd904be 605 break;
ansond 9:a254fcd904be 606 default:
ansond 9:a254fcd904be 607 // wrong verb for this call interface...
ansond 9:a254fcd904be 608 this->logger()->log("invoke: invalid call: must be either GET or DELETE verb if only output buffer is provided");
ansond 9:a254fcd904be 609 break;
ansond 9:a254fcd904be 610 }
ansond 9:a254fcd904be 611 return response;
ansond 0:518b1ca956fc 612 }
ansond 0:518b1ca956fc 613
ansond 0:518b1ca956fc 614 // Salesforce.com Invoke: defaults to POST with JSON input data type
ansond 9:a254fcd904be 615 char *SalesforceInterface::invoke(const char *url,const char *input_data,const int input_data_len,char *output_buffer,int output_buffer_length) {
ansond 9:a254fcd904be 616 return this->invoke(url,JSON,input_data,input_data_len,output_buffer,output_buffer_length);
ansond 0:518b1ca956fc 617 }
ansond 0:518b1ca956fc 618
ansond 0:518b1ca956fc 619 // Salesforce.com Invoke: defaults to POST with variable input data type
ansond 9:a254fcd904be 620 char *SalesforceInterface::invoke(const char *url,const InputDataTypes input_type,const char *input_data,const int input_data_len,char *output_buffer,int output_buffer_length) {
ansond 9:a254fcd904be 621 return this->invoke(url,input_type,input_data,input_data_len,output_buffer,output_buffer_length,POST);
ansond 0:518b1ca956fc 622 }
ansond 0:518b1ca956fc 623
ansond 0:518b1ca956fc 624 // Salesforce.com Invoke: full fidelity method
ansond 9:a254fcd904be 625 char *SalesforceInterface::invoke(const char *url,const InputDataTypes input_type,const char *input_data,const int input_data_len,char *output_buffer,int output_buffer_length,const HttpVerb verb) {
ansond 7:97ea5ef906f7 626 // initialize our invocation status and response code
ansond 7:97ea5ef906f7 627 this->m_http_response_code = -1;
ansond 7:97ea5ef906f7 628 this->m_http_status = HTTP_ERROR;
ansond 7:97ea5ef906f7 629
ansond 7:97ea5ef906f7 630 // param check: make sure that we at least have an output buffer and URL
ansond 9:a254fcd904be 631 if (url != NULL && strlen(url) > 0 && output_buffer != NULL && output_buffer_length > 0) {
ansond 7:97ea5ef906f7 632 // proceed only if we have a valid OAUTH Token
ansond 7:97ea5ef906f7 633 if (this->validOauthToken() == true) {
ansond 7:97ea5ef906f7 634 // use OAUTH headers
ansond 7:97ea5ef906f7 635 this->http()->oauthToken(this->oauth()->access_token.c_str());
ansond 0:518b1ca956fc 636
ansond 7:97ea5ef906f7 637 // reset the redirection url buffer in case we get a redirect...
ansond 7:97ea5ef906f7 638 RESET_BUFFER(this->m_http_redirection_url);
ansond 7:97ea5ef906f7 639 this->http()->setLocationBuf((char *)this->m_http_redirection_url,MAX_BUFFER_LENGTH);
ansond 7:97ea5ef906f7 640
ansond 0:518b1ca956fc 641 // create our output/response buffer
ansond 9:a254fcd904be 642 HTTPText output(output_buffer,output_buffer_length);
ansond 0:518b1ca956fc 643
ansond 0:518b1ca956fc 644 // now make the HTTP(S) request
ansond 0:518b1ca956fc 645 switch(verb) {
ansond 0:518b1ca956fc 646 case GET:
ansond 9:a254fcd904be 647 DEBUG("invoke (GET) URL: %s...",url);
ansond 7:97ea5ef906f7 648 this->m_http_status = this->http()->get(url,&output);
ansond 7:97ea5ef906f7 649 this->m_http_response_code = this->http()->getHTTPResponseCode();
ansond 0:518b1ca956fc 650 break;
ansond 0:518b1ca956fc 651 case DELETE:
ansond 9:a254fcd904be 652 DEBUG("invoke (DEL) URL: %s...",url);
ansond 7:97ea5ef906f7 653 this->m_http_status = this->http()->del(url,&output);
ansond 7:97ea5ef906f7 654 this->m_http_response_code = this->http()->getHTTPResponseCode();
ansond 0:518b1ca956fc 655 break;
ansond 0:518b1ca956fc 656 case POST:
ansond 0:518b1ca956fc 657 if (input_data != NULL && input_data_len > 0) {
ansond 0:518b1ca956fc 658 if (input_type == JSON) {
ansond 9:a254fcd904be 659 DEBUG("invoke (POST-JSON) URL: %s...",url);
ansond 7:97ea5ef906f7 660 HTTPJson input_json((char *)input_data,(int)input_data_len);
ansond 7:97ea5ef906f7 661 this->m_http_status = this->http()->post(url,input_json,&output);
ansond 7:97ea5ef906f7 662 this->m_http_response_code = this->http()->getHTTPResponseCode();
ansond 0:518b1ca956fc 663 }
ansond 0:518b1ca956fc 664 else {
ansond 9:a254fcd904be 665 DEBUG("invoke (POST-TEXT) URL: %s...",url);
ansond 7:97ea5ef906f7 666 HTTPText input_text((char *)input_data,(int)input_data_len);
ansond 7:97ea5ef906f7 667 this->m_http_status = this->http()->post(url,input_text,&output);
ansond 7:97ea5ef906f7 668 this->m_http_response_code = this->http()->getHTTPResponseCode();
ansond 0:518b1ca956fc 669 }
ansond 0:518b1ca956fc 670 }
ansond 0:518b1ca956fc 671 else {
ansond 0:518b1ca956fc 672 // no input buffer!
ansond 0:518b1ca956fc 673 this->logger()->log("invoke: ERROR HTTP(POST) requested but no input data provided... returning NULL");
ansond 0:518b1ca956fc 674 }
ansond 0:518b1ca956fc 675 break;
ansond 0:518b1ca956fc 676 case PUT:
ansond 0:518b1ca956fc 677 if (input_data != NULL && input_data_len > 0) {
ansond 0:518b1ca956fc 678 if (input_type == JSON) {
ansond 9:a254fcd904be 679 DEBUG("invoke (PUT-JSON) URL: %s...",url);
ansond 7:97ea5ef906f7 680 HTTPJson input_json((char *)input_data,(int)input_data_len);
ansond 7:97ea5ef906f7 681 this->m_http_status = this->http()->put(url,input_json,&output);
ansond 7:97ea5ef906f7 682 this->m_http_response_code = this->http()->getHTTPResponseCode();
ansond 0:518b1ca956fc 683 }
ansond 0:518b1ca956fc 684 else {
ansond 9:a254fcd904be 685 DEBUG("invoke (PUT-TEXT) URL: %s...",url);
ansond 7:97ea5ef906f7 686 HTTPText input_text((char *)input_data,(int)input_data_len);
ansond 7:97ea5ef906f7 687 this->m_http_status = this->http()->put(url,input_text,&output);
ansond 7:97ea5ef906f7 688 this->m_http_response_code = this->http()->getHTTPResponseCode();
ansond 0:518b1ca956fc 689 }
ansond 0:518b1ca956fc 690 }
ansond 0:518b1ca956fc 691 else {
ansond 0:518b1ca956fc 692 // no input buffer!
ansond 0:518b1ca956fc 693 this->logger()->log("invoke: ERROR HTTP(PUT) requested but no input data provided... returning NULL");
ansond 0:518b1ca956fc 694 }
ansond 0:518b1ca956fc 695 break;
ansond 0:518b1ca956fc 696 default:
ansond 0:518b1ca956fc 697 // invalid HTTP verb
ansond 0:518b1ca956fc 698 this->logger()->log("invoke: ERROR invalid HTTP verb (%d) provided... returning NULL",verb);
ansond 0:518b1ca956fc 699 break;
ansond 0:518b1ca956fc 700 }
ansond 0:518b1ca956fc 701 }
ansond 7:97ea5ef906f7 702 else {
ansond 7:97ea5ef906f7 703 // no OAUTH Token
ansond 7:97ea5ef906f7 704 this->logger()->log("unable to acquire OAUTH token for credentials provided. Unable to invoke API...");
ansond 7:97ea5ef906f7 705 }
ansond 0:518b1ca956fc 706 }
ansond 0:518b1ca956fc 707 else {
ansond 0:518b1ca956fc 708 // no credentials
ansond 0:518b1ca956fc 709 this->logger()->log("no/incomplete salesforce.com credentials provided. Unable to invoke API...");
ansond 0:518b1ca956fc 710 }
ansond 0:518b1ca956fc 711
ansond 7:97ea5ef906f7 712 // process any return results that we have
ansond 7:97ea5ef906f7 713 if (this->httpStatus() == HTTP_OK || this->httpStatus() == HTTP_REDIRECT) {
ansond 7:97ea5ef906f7 714 // do we have any redirections?
ansond 17:6c774354b599 715 if (this->httpResponseCodeInRange(300) /* REDIRECT */ && strlen(this->m_http_redirection_url) > 0) {
ansond 7:97ea5ef906f7 716 // we have a redirect - so reset the output buffer
ansond 9:a254fcd904be 717 memset(output_buffer,0,output_buffer_length);
ansond 7:97ea5ef906f7 718
ansond 7:97ea5ef906f7 719 // we have to make a copy of the redirection URL - this is because the subsequent invoke() will wipe our current one clean
ansond 7:97ea5ef906f7 720 ALLOC_BUFFER(redirect_url);
ansond 7:97ea5ef906f7 721 strcpy(redirect_url,this->m_http_redirection_url);
ansond 7:97ea5ef906f7 722
ansond 7:97ea5ef906f7 723 // repeat with the redirection URL
ansond 7:97ea5ef906f7 724 DEBUG("invoke: redirecting to: %s",redirect_url);
ansond 9:a254fcd904be 725 return this->invoke((const char *)redirect_url,input_type,input_data,input_data_len,output_buffer,output_buffer_length,verb);
ansond 7:97ea5ef906f7 726 }
ansond 17:6c774354b599 727 else if (this->httpResponseCodeInRange(300) /* REDIRECT */) {
ansond 7:97ea5ef906f7 728 // error - got a redirect but have no URL
ansond 7:97ea5ef906f7 729 this->logger()->log("invoke error: received redirect but no URL...");
ansond 7:97ea5ef906f7 730 this->m_http_status = HTTP_ERROR;
ansond 7:97ea5ef906f7 731 }
ansond 7:97ea5ef906f7 732 }
ansond 7:97ea5ef906f7 733
ansond 0:518b1ca956fc 734 // return the response in the output buffer
ansond 9:a254fcd904be 735 if (this->httpStatus() == HTTP_OK || this->httpStatus() == HTTP_REDIRECT) return output_buffer;
ansond 7:97ea5ef906f7 736 else this->logger()->log("invocation failed with HTTP error code=%d status=%d",this->httpResponseCode(),this->httpStatus());
ansond 0:518b1ca956fc 737 return NULL;
ansond 0:518b1ca956fc 738 }
ansond 8:47db53cd5884 739
ansond 15:89044c68ad36 740 // find the specific URL in our salesforce token
ansond 8:47db53cd5884 741 char *SalesforceInterface::getSalesforceURL(char *key,char *url_buffer,int url_buffer_length) {
ansond 15:89044c68ad36 742 // due to MbedJSONValue limitations - we have to manually pull out the specific JSON from our salesforce token
ansond 8:47db53cd5884 743 int start = (int)strstr(this->m_salesforce_id,SF_URLS_START_TOKEN);
ansond 8:47db53cd5884 744 if (start >= 0) {
ansond 8:47db53cd5884 745 start += strlen(SF_URLS_START_TOKEN);
ansond 8:47db53cd5884 746 int stop = (int)strstr((char *)start,SF_URLS_STOP_TOKEN);
ansond 8:47db53cd5884 747 if (stop >= 0 && stop > start) {
ansond 8:47db53cd5884 748 // calculate the length
ansond 8:47db53cd5884 749 int length = stop - start + 1;
ansond 8:47db53cd5884 750
ansond 15:89044c68ad36 751 // copy over the "urls" json from the salesforce token
ansond 8:47db53cd5884 752 ALLOC_BUFFER(urls);
ansond 8:47db53cd5884 753 int start_index = (start - (int)this->m_salesforce_id);
ansond 8:47db53cd5884 754 for(int i=0;i<length;++i) urls[i] = this->m_salesforce_id[start_index+i];
ansond 8:47db53cd5884 755
ansond 8:47db53cd5884 756 // use MbedJSONValue to parse the "urls" json
ansond 8:47db53cd5884 757 MbedJSONValue parsed_urls;
ansond 8:47db53cd5884 758 parse(parsed_urls,urls);
ansond 8:47db53cd5884 759
ansond 8:47db53cd5884 760 // find the appropriate URL and copy it
ansond 8:47db53cd5884 761 string target_url = parsed_urls[key].get<std::string>();
ansond 8:47db53cd5884 762
ansond 8:47db53cd5884 763 // replace the version of the string with our selected salesforce API version
ansond 8:47db53cd5884 764 string sf_version(this->getSalesforceAPIVersion());
ansond 8:47db53cd5884 765 string version_tag(SF_URL_API_VER_TOKEN);
ansond 8:47db53cd5884 766 this->replace(target_url,version_tag,sf_version);
ansond 8:47db53cd5884 767
ansond 8:47db53cd5884 768 // copy the final URL to our putput
ansond 8:47db53cd5884 769 memset(url_buffer,0,url_buffer_length);
ansond 8:47db53cd5884 770 strcpy(url_buffer,target_url.c_str());
ansond 8:47db53cd5884 771
ansond 8:47db53cd5884 772 // return the URL
ansond 8:47db53cd5884 773 return url_buffer;
ansond 8:47db53cd5884 774 }
ansond 8:47db53cd5884 775 }
ansond 8:47db53cd5884 776 return NULL;
ansond 8:47db53cd5884 777 }
ansond 8:47db53cd5884 778
ansond 8:47db53cd5884 779 // simple char array replacement (modifies input string!)
ansond 8:47db53cd5884 780 void SalesforceInterface::replace(char *str,char orig_char,char new_char) {
ansond 8:47db53cd5884 781 int length = strlen(str);
ansond 8:47db53cd5884 782 for(int i=0;i<length;++i) if (str[i] == orig_char) str[i] = new_char;
ansond 8:47db53cd5884 783 }
ansond 8:47db53cd5884 784
ansond 8:47db53cd5884 785 //
ansond 8:47db53cd5884 786 // substring replacement
ansond 8:47db53cd5884 787 // Credit: http://stackoverflow.com/questions/4643512/replace-substring-with-another-substring-c
ansond 8:47db53cd5884 788 //
ansond 8:47db53cd5884 789 void SalesforceInterface::replace(string& line, string& oldString, string& newString) {
ansond 8:47db53cd5884 790 const size_t oldSize = oldString.length();
ansond 8:47db53cd5884 791
ansond 8:47db53cd5884 792 // do nothing if line is shorter than the string to find
ansond 8:47db53cd5884 793 if( oldSize > line.length() ) return;
ansond 8:47db53cd5884 794
ansond 8:47db53cd5884 795 const size_t newSize = newString.length();
ansond 8:47db53cd5884 796 for( size_t pos = 0; ; pos += newSize ) {
ansond 8:47db53cd5884 797
ansond 8:47db53cd5884 798 // Locate the substring to replace
ansond 8:47db53cd5884 799 pos = line.find( oldString, pos );
ansond 8:47db53cd5884 800 if( pos == string::npos ) return;
ansond 8:47db53cd5884 801 if( oldSize == newSize ) {
ansond 8:47db53cd5884 802
ansond 8:47db53cd5884 803 // if they're same size, use std::string::replace
ansond 8:47db53cd5884 804 line.replace( pos, oldSize, newString );
ansond 8:47db53cd5884 805 }
ansond 8:47db53cd5884 806 else {
ansond 8:47db53cd5884 807
ansond 8:47db53cd5884 808 // if not same size, replace by erasing and inserting
ansond 8:47db53cd5884 809 line.erase( pos, oldSize );
ansond 8:47db53cd5884 810 line.insert( pos, newString );
ansond 8:47db53cd5884 811 }
ansond 8:47db53cd5884 812 }
ansond 17:6c774354b599 813 }
ansond 17:6c774354b599 814
ansond 17:6c774354b599 815 // validate that a given HTTP result code is in the "n" range
ansond 17:6c774354b599 816 bool SalesforceInterface::httpResponseCodeInRange(int n) {
ansond 17:6c774354b599 817 int http_response = this->httpResponseCode();
ansond 17:6c774354b599 818 int diff = http_response - n;
ansond 17:6c774354b599 819 if (diff >= 0 && diff < 100) return true;
ansond 17:6c774354b599 820 return false;
ansond 20:0d6abaf6d7c5 821 }
ansond 20:0d6abaf6d7c5 822
ansond 20:0d6abaf6d7c5 823 // min() method
ansond 20:0d6abaf6d7c5 824 int SalesforceInterface::min(int value1,int value2) {
ansond 20:0d6abaf6d7c5 825 if (value1 < value2) return value1;
ansond 20:0d6abaf6d7c5 826 return value2;
ansond 9:a254fcd904be 827 }