Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.force</groupId>
<artifactId>dataloader</artifactId>
<version>66.0.0</version>
<version>67.0.0</version>
<packaging>jar</packaging>
<name>Salesforce Data Loader</name>
<url>https://github.com/forcedotcom/dataloader</url>
Expand Down Expand Up @@ -51,7 +51,7 @@
<dependency>
<groupId>com.force.api</groupId>
<artifactId>force-partner-api</artifactId>
<version>66.0.0</version>
<version>67.0.0</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
Expand Down
28 changes: 23 additions & 5 deletions src/main/java/com/salesforce/dataloader/client/ClientBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.salesforce.dataloader.config.AppConfig;
import com.salesforce.dataloader.config.Messages;
import com.salesforce.dataloader.controller.Controller;
import com.salesforce.dataloader.dao.DataAccessObjectFactory;
import com.salesforce.dataloader.exception.ParameterLoadException;
import com.salesforce.dataloader.util.AppUtil;
import com.sforce.soap.partner.Connector;
Expand Down Expand Up @@ -137,11 +138,20 @@ public final boolean connect(SessionInfo sess) {

public static String getClientName(AppConfig cfg) {
return getClientName(cfg.isBulkAPIEnabled(), cfg.isBulkV2APIEnabled(),
cfg.isBatchMode(), cfg.isExternalClientAppConfigured(), Controller.APP_VERSION);
cfg.isBatchMode(), cfg.isExternalClientAppConfigured(), Controller.APP_VERSION,
cfg.getString(AppConfig.PROP_DAO_TYPE));
}

// Kept for source-compatibility with existing tests; delegates to the 6-arg overload below.
static String getClientName(boolean bulkAPI, boolean bulkV2API,
boolean batchMode, boolean externalClientApp, String appVersion) {
return getClientName(bulkAPI, bulkV2API, batchMode, externalClientApp, appVersion, null);
}

// W-22717496: append DAO-type suffix so apusg can measure direct-DB-access usage
static String getClientName(boolean bulkAPI, boolean bulkV2API,
boolean batchMode, boolean externalClientApp,
String appVersion, String daoType) {
String apiType = PARTNER_API_CLIENT_TYPE;
if (bulkAPI) {
apiType = BULK_API_CLIENT_TYPE;
Expand All @@ -153,10 +163,18 @@ static String getClientName(boolean bulkAPI, boolean bulkV2API,
? ""
: (batchMode ? BATCH_CLIENT_STRING : UI_CLIENT_STRING);

return new StringBuilder(32).append(BASE_CLIENT_NAME).append(apiType).append(interfaceType)
StringBuilder sb = new StringBuilder(32).append(BASE_CLIENT_NAME).append(apiType).append(interfaceType)
.append("/")
.append(appVersion)
.toString();
.append(appVersion);

if (batchMode && daoType != null) {
if (DataAccessObjectFactory.DATABASE_READ_TYPE.equalsIgnoreCase(daoType)) {
sb.append("/DBR");
} else if (DataAccessObjectFactory.DATABASE_WRITE_TYPE.equalsIgnoreCase(daoType)) {
sb.append("/DBW");
}
}
return sb.toString();
}

public static synchronized String getAPIVersionForTheSession() {
Expand All @@ -172,7 +190,7 @@ public ConnectorConfig getConnectorConfig() {
cc.setTransportFactory(new TransportFactoryImpl());
cc.setSessionId(getSessionId());
cc.setRequestHeader(SFORCE_CALL_OPTIONS_HEADER,
"client=" + ClientBase.getClientName(this.appConfig));
"client=" + ClientBase.getClientName(this.appConfig));
// set authentication credentials
// blank username is not acceptible
String username = appConfig.getString(AppConfig.PROP_USERNAME);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,15 @@
*/
package com.salesforce.dataloader.client;

import com.salesforce.dataloader.config.AppConfig;
import com.salesforce.dataloader.controller.Controller;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
* Unit tests for {@link ClientBase#getClientName}.
Expand Down Expand Up @@ -97,4 +102,131 @@ public void eca_ignoresBatchMode() {
assertEquals("DataLoaderPartner/65.0.0", name);
assertFalse("ECA path should not include Batch suffix", name.contains("Batch"));
}

// --- DAO type suffix (W-22717496) ---

@Test
public void batch_partner_databaseRead() {
assertEquals("DataLoaderPartnerBatch/65.0.0/DBR",
ClientBase.getClientName(false, false, true, false, VERSION, "databaseRead"));
}

@Test
public void batch_partner_databaseWrite() {
assertEquals("DataLoaderPartnerBatch/65.0.0/DBW",
ClientBase.getClientName(false, false, true, false, VERSION, "databaseWrite"));
}

@Test
public void batch_bulk_databaseRead() {
assertEquals("DataLoaderBulkBatch/65.0.0/DBR",
ClientBase.getClientName(true, false, true, false, VERSION, "databaseRead"));
}

@Test
public void batch_bulkv2_databaseWrite() {
assertEquals("DataLoaderBulkv2Batch/65.0.0/DBW",
ClientBase.getClientName(false, true, true, false, VERSION, "databaseWrite"));
}

@Test
public void batch_csvRead_unchanged() {
assertEquals("DataLoaderPartnerBatch/65.0.0",
ClientBase.getClientName(false, false, true, false, VERSION, "csvRead"));
}

@Test
public void batch_csvWrite_unchanged() {
assertEquals("DataLoaderPartnerBatch/65.0.0",
ClientBase.getClientName(false, false, true, false, VERSION, "csvWrite"));
}

@Test
public void batch_databaseRead_caseInsensitive() {
assertEquals("DataLoaderPartnerBatch/65.0.0/DBR",
ClientBase.getClientName(false, false, true, false, VERSION, "DATABASEREAD"));
}

@Test
public void ui_databaseRead_noSuffix() {
assertEquals("DataLoaderPartnerUI/65.0.0",
ClientBase.getClientName(false, false, false, false, VERSION, "databaseRead"));
}

@Test
public void eca_batch_databaseWrite() {
assertEquals("DataLoaderBulk/65.0.0/DBW",
ClientBase.getClientName(true, false, true, true, VERSION, "databaseWrite"));
}

// W-19625612 regression guard: ECA + UI + database* must NOT acquire a suffix.
// PR 16 requires ECA paths to emit a neutral name that doesn't match any
// blocked legacy Connected App; appending /DBR or /DBW to a UI-mode header
// would break that contract if the suffix logic ever drifted away from
// batchMode-gating.
@Test
public void eca_ui_databaseRead_noSuffix() {
assertEquals("DataLoaderBulk/65.0.0",
ClientBase.getClientName(true, false, false, true, VERSION, "databaseRead"));
}

@Test
public void eca_ui_databaseWrite_noSuffix() {
assertEquals("DataLoaderPartner/65.0.0",
ClientBase.getClientName(false, false, false, true, VERSION, "databaseWrite"));
}

@Test
public void dao_type_null_unchanged() {
assertEquals("DataLoaderPartnerBatch/65.0.0",
ClientBase.getClientName(false, false, true, false, VERSION, (String) null));
}

// --- AppConfig wiring (W-22717496): the single-arg overload must read PROP_DAO_TYPE ---

private AppConfig mockCfg(boolean bulk, boolean bulkV2, boolean batch, boolean eca, String daoType) {
AppConfig cfg = mock(AppConfig.class);
when(cfg.isBulkAPIEnabled()).thenReturn(bulk);
when(cfg.isBulkV2APIEnabled()).thenReturn(bulkV2);
when(cfg.isBatchMode()).thenReturn(batch);
when(cfg.isExternalClientAppConfigured()).thenReturn(eca);
when(cfg.getString(AppConfig.PROP_DAO_TYPE)).thenReturn(daoType);
return cfg;
}

@Test
public void appConfig_batch_databaseRead_emitsDBR() {
String name = ClientBase.getClientName(mockCfg(true, false, true, false, "databaseRead"));
assertTrue("expected /DBR suffix, got: " + name, name.endsWith("/DBR"));
assertTrue(name.startsWith("DataLoaderBulkBatch/"));
}

@Test
public void appConfig_batch_databaseWrite_emitsDBW() {
String name = ClientBase.getClientName(mockCfg(false, true, true, false, "databaseWrite"));
assertTrue("expected /DBW suffix, got: " + name, name.endsWith("/DBW"));
assertTrue(name.startsWith("DataLoaderBulkv2Batch/"));
}

@Test
public void appConfig_batch_csvRead_noSuffix() {
String name = ClientBase.getClientName(mockCfg(false, false, true, false, "csvRead"));
assertFalse("CSV must not get DAO suffix, got: " + name, name.endsWith("/DBR"));
assertFalse(name.endsWith("/DBW"));
assertEquals("DataLoaderPartnerBatch/" + Controller.APP_VERSION, name);
}

@Test
public void appConfig_ui_databaseRead_noSuffix() {
String name = ClientBase.getClientName(mockCfg(false, false, false, false, "databaseRead"));
assertFalse("UI mode must not get DAO suffix, got: " + name, name.endsWith("/DBR"));
assertEquals("DataLoaderPartnerUI/" + Controller.APP_VERSION, name);
}

@Test
public void appConfig_batch_nullDaoType_noSuffix() {
String name = ClientBase.getClientName(mockCfg(false, false, true, false, null));
assertFalse(name.endsWith("/DBR"));
assertFalse(name.endsWith("/DBW"));
}
}
Loading