Interface for invoking Salesforce.com REST calls over SSL with OAUTH authentication. This interface is designed to simplify the interaction between mbed devices and salesforce.com web services.

Dependencies:   HTTPClient-SSL MbedJSONValue

Dependents:   StatusReporter

Committer:
ansond
Date:
Fri Sep 26 04:34:33 2014 +0000
Revision:
22:3363752cd523
Parent:
21:e5a4471a46fb
revamped to use new salesforce interface

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