PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/connector/src/main/java/com/gooddata/connector/SfdcConnector.java

https://github.com/chrbayer84/GoodData-CL
Java | 598 lines | 384 code | 37 blank | 177 comment | 90 complexity | 85b4e4906cc4d839e61e7cde2b205c01 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /*
  2. * Copyright (c) 2009, GoodData Corporation. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without modification, are permitted provided
  5. * that the following conditions are met:
  6. *
  7. * * Redistributions of source code must retain the above copyright notice, this list of conditions and
  8. * the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
  10. * and the following disclaimer in the documentation and/or other materials provided with the distribution.
  11. * * Neither the name of the GoodData Corporation nor the names of its contributors may be used to endorse
  12. * or promote products derived from this software without specific prior written permission.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
  15. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  16. * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  17. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  18. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  19. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  20. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  21. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  22. */
  23. package com.gooddata.connector;
  24. import com.gooddata.exception.ProcessingException;
  25. import com.gooddata.exception.SfdcException;
  26. import com.gooddata.modeling.model.SourceColumn;
  27. import com.gooddata.modeling.model.SourceSchema;
  28. import com.gooddata.processor.CliParams;
  29. import com.gooddata.processor.Command;
  30. import com.gooddata.processor.ProcessingContext;
  31. import com.gooddata.transform.Transformer;
  32. import com.gooddata.util.CSVWriter;
  33. import com.gooddata.util.FileUtil;
  34. import com.gooddata.util.StringUtil;
  35. import com.sforce.soap.partner.*;
  36. import com.sforce.soap.partner.fault.*;
  37. import com.sforce.soap.partner.sobject.SObject;
  38. import org.apache.axis.message.MessageElement;
  39. import org.apache.log4j.Logger;
  40. import org.joda.time.DateTime;
  41. import java.io.File;
  42. import java.io.IOException;
  43. import java.rmi.RemoteException;
  44. import java.util.*;
  45. /**
  46. * GoodData SFDC Connector
  47. *
  48. * @author zd <zd@gooddata.com>
  49. * @version 1.0
  50. */
  51. public class SfdcConnector extends AbstractConnector implements Connector {
  52. private static Logger l = Logger.getLogger(SfdcConnector.class);
  53. private String sfdcUsername;
  54. private String sfdcPassword;
  55. private String sfdcQuery;
  56. private String sfdcToken;
  57. private String sfdcHostname = "www.salesforce.com";
  58. private String clientID;
  59. /**
  60. * Creates a new SFDC connector
  61. */
  62. protected SfdcConnector() {
  63. super();
  64. }
  65. /**
  66. * Creates a new SFDC connector
  67. *
  68. * @return a new instance of the SFDC connector
  69. */
  70. public static SfdcConnector createConnector() {
  71. return new SfdcConnector();
  72. }
  73. /**
  74. * Executes the SFDC query, returns one row only. This is useful for metadata inspection purposes
  75. *
  76. * @param binding SFDC stub
  77. * @param sfdcQuery SFDC SOOL query
  78. * @param clientID SFDC partner client ID
  79. * @return results as List of SObjects
  80. * @throws SfdcException in case of SFDC communication errors
  81. */
  82. protected static SObject executeQueryFirstRow(SoapBindingStub binding, String sfdcQuery, String clientID) throws SfdcException {
  83. l.debug("Executing SFDC query " + sfdcQuery);
  84. List<SObject> result = new ArrayList<SObject>();
  85. QueryOptions qo = new QueryOptions();
  86. qo.setBatchSize(1);
  87. binding.setHeader(new SforceServiceLocator().getServiceName().getNamespaceURI(),
  88. "QueryOptions", qo);
  89. try {
  90. QueryResult qr = binding.query(sfdcQuery);
  91. if (qr.getSize() > 0) {
  92. SObject[] sObjects = qr.getRecords();
  93. result.addAll(Arrays.asList(sObjects));
  94. }
  95. } catch (ApiQueryFault ex) {
  96. l.debug("Executing SFDC query failed", ex);
  97. throw new SfdcException("Failed to execute SFDC query.", ex);
  98. } catch (UnexpectedErrorFault e) {
  99. l.debug("Executing SFDC query failed", e);
  100. throw new SfdcException("Failed to execute SFDC query.", e);
  101. } catch (InvalidIdFault e) {
  102. l.debug("Executing SFDC query failed", e);
  103. throw new SfdcException("Failed to execute SFDC query.", e);
  104. } catch (InvalidQueryLocatorFault e) {
  105. l.debug("Executing SFDC query failed", e);
  106. throw new SfdcException("Failed to execute SFDC query.", e);
  107. } catch (RemoteException e) {
  108. l.debug("Executing SFDC query failed", e);
  109. throw new SfdcException("Failed to execute SFDC query.", e);
  110. }
  111. l.debug("Finihed SFDC query execution.");
  112. if (result.size() > 0)
  113. return result.get(0);
  114. else
  115. return null;
  116. }
  117. /**
  118. * Retrieves the object's metadata
  119. *
  120. * @param c SFDC stub
  121. * @param name SFDC object name
  122. * @return Map of fields
  123. * @throws RemoteException communication error
  124. */
  125. protected static Map<String, Field> describeObject(SoapBindingStub c, String name) throws RemoteException {
  126. l.debug("Retrieving SFDC object " + name + " metadata.");
  127. Map<String, Field> result = new HashMap<String, Field>();
  128. DescribeSObjectResult describeSObjectResult = c.describeSObject(name);
  129. if (!(describeSObjectResult == null)) {
  130. Field[] fields = describeSObjectResult.getFields();
  131. if (fields != null) {
  132. for (Field field : fields) {
  133. result.put(field.getName(), field);
  134. }
  135. }
  136. }
  137. l.debug("SFDC object " + name + " metadata retrieved.");
  138. return result;
  139. }
  140. /**
  141. * Saves a template of the config file
  142. *
  143. * @param name new schema name
  144. * @param configFileName config file name
  145. * @param sfdcUsr SFDC username
  146. * @param sfdcPsw SFDC password
  147. * @param sfdcToken SFDC security token
  148. * @param query SFDC query
  149. * @param partnerId SFDC partner ID
  150. * @throws IOException if there is a problem with writing the config file
  151. */
  152. public static void saveConfigTemplate(String name, String configFileName, String sfdcHostname, String sfdcUsr, String sfdcPsw, String sfdcToken, String partnerId,
  153. String query)
  154. throws IOException {
  155. l.debug("Saving SFDC config template.");
  156. SourceSchema s = SourceSchema.createSchema(name);
  157. SoapBindingStub c = connect(sfdcHostname, sfdcUsr, sfdcPsw, sfdcToken, partnerId);
  158. SObject result = executeQueryFirstRow(c, query, partnerId);
  159. if (result != null) {
  160. Map<String, Field> fields = describeObject(c, result.getType());
  161. for (MessageElement column : result.get_any()) {
  162. String nm = column.getName();
  163. String tp = getColumnType(fields, nm);
  164. if (tp.equals(SourceColumn.LDM_TYPE_DATE)) {
  165. SourceColumn sc = new SourceColumn(nm, tp, nm, name);
  166. sc.setFormat("yyyy-MM-dd");
  167. s.addColumn(sc);
  168. } else {
  169. SourceColumn sc = new SourceColumn(nm, tp, nm, name);
  170. s.addColumn(sc);
  171. }
  172. }
  173. } else {
  174. l.debug("The SFDC query hasn't returned any row.");
  175. throw new SfdcException("The SFDC query hasn't returned any row.");
  176. }
  177. s.writeConfig(new File(configFileName));
  178. l.debug("Saved SFDC config template.");
  179. }
  180. /**
  181. * Derives the LDM type from the SFDC type
  182. *
  183. * @param fields SFDC object metadata
  184. * @param fieldName the field name
  185. * @return LDM type
  186. */
  187. protected static String getColumnType(Map<String, Field> fields, String fieldName) {
  188. String type = SourceColumn.LDM_TYPE_ATTRIBUTE;
  189. Field f = fields.get(fieldName);
  190. if (f != null) {
  191. FieldType t = f.getType();
  192. if (t.getValue().equalsIgnoreCase("id"))
  193. type = SourceColumn.LDM_TYPE_CONNECTION_POINT;
  194. else if (t.getValue().equalsIgnoreCase("string"))
  195. type = SourceColumn.LDM_TYPE_ATTRIBUTE;
  196. else if (t.getValue().equalsIgnoreCase("currency"))
  197. type = SourceColumn.LDM_TYPE_FACT;
  198. else if (t.getValue().equalsIgnoreCase("boolean"))
  199. type = SourceColumn.LDM_TYPE_ATTRIBUTE;
  200. else if (t.getValue().equalsIgnoreCase("reference"))
  201. type = SourceColumn.LDM_TYPE_REFERENCE;
  202. else if (t.getValue().equalsIgnoreCase("date"))
  203. type = SourceColumn.LDM_TYPE_DATE;
  204. else if (t.getValue().equalsIgnoreCase("datetime"))
  205. type = SourceColumn.LDM_TYPE_DATE;
  206. }
  207. return type;
  208. }
  209. /**
  210. * {@inheritDoc}
  211. */
  212. public void extract(String file, boolean transform) throws IOException {
  213. File dataFile = new File(file);
  214. l.debug("Extracting SFDC data to file=" + dataFile.getAbsolutePath());
  215. CSVWriter cw = FileUtil.createUtf8CsvEscapingWriter(dataFile);
  216. Transformer t = Transformer.create(schema);
  217. String[] header = t.getHeader(transform);
  218. cw.writeNext(header);
  219. SoapBindingStub c = connect(getSfdcHostname(), getSfdcUsername(), getSfdcPassword(), getSfdcToken(), getClientID());
  220. l.debug("Executing SFDC query " + sfdcQuery);
  221. QueryOptions qo = new QueryOptions();
  222. qo.setBatchSize(500);
  223. c.setHeader(new SforceServiceLocator().getServiceName().getNamespaceURI(), "QueryOptions", qo);
  224. String[] colTypes = null;
  225. boolean firstBatch = true;
  226. int rowCnt = 0;
  227. try {
  228. QueryResult qr = c.query(sfdcQuery);
  229. boolean isdone = false;
  230. do {
  231. SObject[] sObjects = qr.getRecords();
  232. if (sObjects != null && sObjects.length > 0) {
  233. l.debug("Started retrieving SFDC data.");
  234. boolean firstRow = true;
  235. for (SObject srow : sObjects) {
  236. if (firstBatch && firstRow) {
  237. SObject hdr = sObjects[0];
  238. Map<String, Field> fields = describeObject(c, hdr.getType());
  239. MessageElement[] frCols = hdr.get_any();
  240. colTypes = new String[frCols.length];
  241. for (int i = 0; i < frCols.length; i++) {
  242. String nm = frCols[i].getName();
  243. colTypes[i] = getColumnType(fields, nm);
  244. }
  245. firstRow = false;
  246. }
  247. MessageElement[] cols = srow.get_any();
  248. Object[] row = new Object[cols.length];
  249. for (int i = 0; i < row.length; i++) {
  250. if (colTypes[i].equalsIgnoreCase(SourceColumn.LDM_TYPE_DATE)) {
  251. row[i] = new DateTime(cols[i].getValue());
  252. } else {
  253. row[i] = cols[i].getValue();
  254. }
  255. }
  256. String[] nrow = null;
  257. if (transform) {
  258. nrow = t.transformRow(row, DATE_LENGTH_UNRESTRICTED);
  259. } else {
  260. nrow = new String[row.length];
  261. for (int i = 0; i < row.length; i++) {
  262. nrow[i] = row[i].toString();
  263. }
  264. }
  265. cw.writeNext(nrow);
  266. cw.flush();
  267. rowCnt++;
  268. }
  269. isdone = qr.isDone();
  270. if (!isdone) {
  271. qr = c.queryMore(qr.getQueryLocator());
  272. firstBatch = false;
  273. }
  274. }
  275. } while (!isdone);
  276. l.debug("Retrieved " + rowCnt + " rows of SFDC data.");
  277. cw.close();
  278. } catch (ApiQueryFault ex) {
  279. l.debug("Executing SFDC query failed", ex);
  280. throw new SfdcException("Failed to execute SFDC query.", ex);
  281. } catch (UnexpectedErrorFault e) {
  282. l.debug("Executing SFDC query failed", e);
  283. throw new SfdcException("Failed to execute SFDC query.", e);
  284. } catch (InvalidIdFault e) {
  285. l.debug("Executing SFDC query failed", e);
  286. throw new SfdcException("Failed to execute SFDC query.", e);
  287. } catch (InvalidQueryLocatorFault e) {
  288. l.debug("Executing SFDC query failed", e);
  289. throw new SfdcException("Failed to execute SFDC query.", e);
  290. } catch (RemoteException e) {
  291. l.debug("Executing SFDC query failed", e);
  292. throw new SfdcException("Failed to execute SFDC query.", e);
  293. }
  294. l.debug("Finihed SFDC query execution.");
  295. }
  296. /**
  297. * Connect the SFDC
  298. *
  299. * @param usr SFDC username
  300. * @param psw SFDC pasword
  301. * @param token SFDC security token
  302. * @return SFDC stub
  303. * @throws SfdcException in case of connection issues
  304. */
  305. protected static SoapBindingStub connect(String host, String usr, String psw, String token, String clientID) throws SfdcException {
  306. SoapBindingStub binding;
  307. LoginResult loginResult;
  308. if (token != null) {
  309. psw += token;
  310. }
  311. try {
  312. SforceServiceLocator loc = new SforceServiceLocator();
  313. loc.setSoapEndpointAddress(loc.getSoapAddress().replaceAll("www.salesforce.com", host).replaceAll("login.salesforce.com", host));
  314. binding = (SoapBindingStub) loc.getSoap();
  315. l.debug("Connecting to SFDC.");
  316. // Time out after a minute
  317. binding.setTimeout(60000);
  318. // Test operation
  319. if (clientID != null && clientID.length() > 0) {
  320. CallOptions co = new CallOptions();
  321. co.setClient(clientID);
  322. binding.setHeader(new SforceServiceLocator().getServiceName().getNamespaceURI(), "CallOptions", co);
  323. }
  324. loginResult = binding.login(usr, psw);
  325. } catch (LoginFault ex) {
  326. // The LoginFault derives from AxisFault
  327. ExceptionCode exCode = ex.getExceptionCode();
  328. if (exCode == ExceptionCode.FUNCTIONALITY_NOT_ENABLED) {
  329. l.debug("Error logging into the SFDC. Functionality not enabled.", ex);
  330. throw new SfdcException("Error logging into the SFDC. Functionality not enabled.", ex);
  331. } else if (exCode == ExceptionCode.INVALID_CLIENT) {
  332. l.debug("Error logging into the SFDC. Invalid client.", ex);
  333. throw new SfdcException("Error logging into the SFDC. Invalid client.", ex);
  334. } else if (exCode == ExceptionCode.INVALID_LOGIN) {
  335. l.debug("Error logging into the SFDC. Invalid login.", ex);
  336. throw new SfdcException("Error logging into the SFDC. Invalid login.", ex);
  337. } else if (exCode == ExceptionCode.LOGIN_DURING_RESTRICTED_DOMAIN) {
  338. l.debug("Error logging into the SFDC. Restricred domain.", ex);
  339. throw new SfdcException("Error logging into the SFDC. Restricred domain.", ex);
  340. } else if (exCode == ExceptionCode.LOGIN_DURING_RESTRICTED_TIME) {
  341. l.debug("Error logging into the SFDC. Restricred during time.", ex);
  342. throw new SfdcException("Error logging into the SFDC. Restricred during time.", ex);
  343. } else if (exCode == ExceptionCode.ORG_LOCKED) {
  344. l.debug("Error logging into the SFDC. Organization locked.", ex);
  345. throw new SfdcException("Error logging into the SFDC. Organization locked.", ex);
  346. } else if (exCode == ExceptionCode.PASSWORD_LOCKOUT) {
  347. l.debug("Error logging into the SFDC. Password lock-out.", ex);
  348. throw new SfdcException("Error logging into the SFDC. Password lock-out.", ex);
  349. } else if (exCode == ExceptionCode.SERVER_UNAVAILABLE) {
  350. l.debug("Error logging into the SFDC. Server not available.", ex);
  351. throw new SfdcException("Error logging into the SFDC. Server not available.", ex);
  352. } else if (exCode == ExceptionCode.TRIAL_EXPIRED) {
  353. l.debug("Error logging into the SFDC. Trial expired.", ex);
  354. throw new SfdcException("Error logging into the SFDC. Trial expired.", ex);
  355. } else if (exCode == ExceptionCode.UNSUPPORTED_CLIENT) {
  356. l.debug("Error logging into the SFDC. Unsupported client.", ex);
  357. throw new SfdcException("Error logging into the SFDC. Unsupported client.", ex);
  358. } else {
  359. l.debug("Error logging into the SFDC.", ex);
  360. throw new SfdcException("Error logging into the SFDC.", ex);
  361. }
  362. } catch (Exception ex) {
  363. l.debug("Error logging into the SFDC.", ex);
  364. throw new SfdcException("Error logging into the SFDC.", ex);
  365. }
  366. // Check if the password has expired
  367. if (loginResult.isPasswordExpired()) {
  368. l.debug("An error has occurred. Your password has expired.");
  369. throw new SfdcException("An error has occurred. Your password has expired.");
  370. }
  371. /** Once the client application has logged in successfully, it will use
  372. * the results of the login call to reset the endpoint of the service
  373. * to the virtual server instance that is servicing your organization.
  374. * To do this, the client application sets the ENDPOINT_ADDRESS_PROPERTY
  375. * of the binding object using the URL returned from the LoginResult.
  376. */
  377. binding._setProperty(SoapBindingStub.ENDPOINT_ADDRESS_PROPERTY,
  378. loginResult.getServerUrl());
  379. /** The sample client application now has an instance of the SoapBindingStub
  380. * that is pointing to the correct endpoint. Next, the sample client application
  381. * sets a persistent SOAP header (to be included on all subsequent calls that
  382. * are made with the SoapBindingStub) that contains the valid sessionId
  383. * for our login credentials. To do this, the sample client application
  384. * creates a new SessionHeader object and set its sessionId property to the
  385. * sessionId property from the LoginResult object.
  386. */
  387. // Create a new session header object and add the session id
  388. // from the login return object
  389. SessionHeader sh = new SessionHeader();
  390. sh.setSessionId(loginResult.getSessionId());
  391. /** Next, the sample client application calls the setHeader method of the
  392. * SoapBindingStub to add the header to all subsequent method calls. This
  393. * header will persist until the SoapBindingStub is destroyed until the header
  394. * is explicitly removed. The "SessionHeader" parameter is the name of the
  395. * header to be added.
  396. */
  397. // set the session header for subsequent call authentication
  398. binding.setHeader(new SforceServiceLocator().getServiceName().getNamespaceURI(),
  399. "SessionHeader", sh);
  400. l.debug("Connected to SFDC.");
  401. return binding;
  402. }
  403. /**
  404. * SFDC username getter
  405. *
  406. * @return SFDC username
  407. */
  408. public String getSfdcUsername() {
  409. return sfdcUsername;
  410. }
  411. /**
  412. * SFDC username setter
  413. *
  414. * @param sfdcUsername SFDC username
  415. */
  416. public void setSfdcUsername(String sfdcUsername) {
  417. this.sfdcUsername = sfdcUsername;
  418. }
  419. /**
  420. * SFDC password getter
  421. *
  422. * @return SFDC password
  423. */
  424. public String getSfdcPassword() {
  425. return sfdcPassword;
  426. }
  427. /**
  428. * SFDC password setter
  429. *
  430. * @param sfdcPassword SFDC password
  431. */
  432. public void setSfdcPassword(String sfdcPassword) {
  433. this.sfdcPassword = sfdcPassword;
  434. }
  435. /**
  436. * SFDC query getter
  437. *
  438. * @return SFDC query
  439. */
  440. public String getSfdcQuery() {
  441. return sfdcQuery;
  442. }
  443. /**
  444. * SFDC query setter
  445. *
  446. * @param sfdcQuery SFDC query
  447. */
  448. public void setSfdcQuery(String sfdcQuery) {
  449. this.sfdcQuery = sfdcQuery;
  450. }
  451. /**
  452. * SFDC security token getter
  453. *
  454. * @return SFDC security token
  455. */
  456. public String getSfdcToken() {
  457. return sfdcToken;
  458. }
  459. /**
  460. * SFDC security token setter
  461. *
  462. * @param sfdcToken SFDC security token
  463. */
  464. public void setSfdcToken(String sfdcToken) {
  465. this.sfdcToken = sfdcToken;
  466. }
  467. /**
  468. * @return the sfdcHostname
  469. */
  470. public String getSfdcHostname() {
  471. return sfdcHostname;
  472. }
  473. /**
  474. * @param sfdcHostname the sfdcHostname to set
  475. */
  476. public void setSfdcHostname(String sfdcHostname) {
  477. this.sfdcHostname = sfdcHostname;
  478. }
  479. public String getClientID() {
  480. return clientID;
  481. }
  482. public void setClientID(String clientID) {
  483. this.clientID = clientID;
  484. }
  485. /**
  486. * {@inheritDoc}
  487. */
  488. public boolean processCommand(Command c, CliParams cli, ProcessingContext ctx) throws ProcessingException {
  489. l.debug("Processing command " + c.getCommand());
  490. try {
  491. if (c.match("GenerateSfdcConfig")) {
  492. generateSfdcConfig(c, cli, ctx);
  493. } else if (c.match("LoadSfdc") || c.match("UseSfdc")) {
  494. loadSfdc(c, cli, ctx);
  495. } else {
  496. l.debug("No match passing the command " + c.getCommand() + " further.");
  497. return super.processCommand(c, cli, ctx);
  498. }
  499. } catch (IOException e) {
  500. throw new ProcessingException(e);
  501. }
  502. l.debug("Processed command " + c.getCommand());
  503. return true;
  504. }
  505. /**
  506. * Loads SFDC data command processor
  507. *
  508. * @param c command
  509. * @param p command line arguments
  510. * @param ctx current processing context
  511. * @throws IOException in case of IO issues
  512. */
  513. private void loadSfdc(Command c, CliParams p, ProcessingContext ctx) throws IOException {
  514. String configFile = c.getParamMandatory("configFile");
  515. String usr = c.getParamMandatory("username");
  516. String psw = c.getParamMandatory("password");
  517. String q = c.getParamMandatory("query");
  518. String t = c.getParam("token");
  519. String host = c.getParam("host");
  520. String partnerId = c.getParam("partnerId");
  521. c.paramsProcessed();
  522. File conf = FileUtil.getFile(configFile);
  523. initSchema(conf.getAbsolutePath());
  524. setSfdcUsername(usr);
  525. setSfdcPassword(psw);
  526. setSfdcToken(t);
  527. setSfdcQuery(q);
  528. setClientID(partnerId);
  529. if (host != null && !"".equals(host)) {
  530. setSfdcHostname(host);
  531. }
  532. // sets the current connector
  533. ctx.setConnector(this);
  534. setProjectId(ctx);
  535. l.info("SFDC Connector successfully loaded (query: " + StringUtil.previewString(q, 256) + ").");
  536. }
  537. /**
  538. * Generates the SFDC config
  539. *
  540. * @param c command
  541. * @param p command line arguments
  542. * @param ctx current processing context
  543. * @throws IOException in case of IO issues
  544. */
  545. private void generateSfdcConfig(Command c, CliParams p, ProcessingContext ctx) throws IOException {
  546. String configFile = c.getParamMandatory("configFile");
  547. String name = c.getParamMandatory("name");
  548. String usr = c.getParamMandatory("username");
  549. String psw = c.getParamMandatory("password");
  550. String token = c.getParam("token");
  551. String query = c.getParamMandatory("query");
  552. String host = c.getParam("host");
  553. if (host == null || "".equals(host)) {
  554. host = sfdcHostname;
  555. }
  556. String partnerId = c.getParam("partnerId");
  557. c.paramsProcessed();
  558. SfdcConnector.saveConfigTemplate(name, configFile, host, usr, psw, token, partnerId, query);
  559. l.info("SFDC Connector configuration successfully generated. See config file: " + configFile);
  560. }
  561. }