This is an automated email from the ASF dual-hosted git repository.
turcsanyi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/main by this push:
new 111c7ac0a4 NIFI-10444 FetchDropbox processor
111c7ac0a4 is described below
commit 111c7ac0a4713973211218f341038720c654169a
Author: krisztina-zsihovszki <[email protected]>
AuthorDate: Mon Aug 29 07:31:39 2022 +0200
NIFI-10444 FetchDropbox processor
NIFI-10444 Add ProxyConfiguration to ListDropbox and FetchDropbox processors
This closes #6401.
Signed-off-by: Peter Turcsanyi <[email protected]>
---
.../nifi-dropbox-processors/pom.xml | 8 +
.../nifi/processors/dropbox/DropboxTrait.java | 73 +++++++++
.../nifi/processors/dropbox/FetchDropbox.java | 151 ++++++++++++++++++
.../nifi/processors/dropbox/ListDropbox.java | 38 ++---
.../services/org.apache.nifi.processor.Processor | 1 +
.../nifi/processors/dropbox/AbstractDropboxIT.java | 4 +-
.../nifi/processors/dropbox/FetchDropboxIT.java | 132 ++++++++++++++++
.../nifi/processors/dropbox/FetchDropboxTest.java | 169 +++++++++++++++++++++
.../nifi/processors/dropbox/ListDropboxIT.java | 16 +-
.../nifi/processors/dropbox/ListDropboxTest.java | 48 +++---
10 files changed, 581 insertions(+), 59 deletions(-)
diff --git
a/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/pom.xml
b/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/pom.xml
index 2391a78f99..3d336653f7 100644
--- a/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/pom.xml
+++ b/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/pom.xml
@@ -39,6 +39,10 @@
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-record</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.nifi</groupId>
+ <artifactId>nifi-proxy-configuration-api</artifactId>
+ </dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-listed-entity</artifactId>
@@ -55,6 +59,10 @@
<artifactId>dropbox-core-sdk</artifactId>
<version>${dropbox.client.version}</version>
</dependency>
+ <dependency>
+ <groupId>com.squareup.okhttp3</groupId>
+ <artifactId>okhttp</artifactId>
+ </dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-mock</artifactId>
diff --git
a/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/main/java/org/apache/nifi/processors/dropbox/DropboxTrait.java
b/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/main/java/org/apache/nifi/processors/dropbox/DropboxTrait.java
new file mode 100644
index 0000000000..6e8548787a
--- /dev/null
+++
b/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/main/java/org/apache/nifi/processors/dropbox/DropboxTrait.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.processors.dropbox;
+
+import com.dropbox.core.DbxRequestConfig;
+import com.dropbox.core.http.HttpRequestor;
+import com.dropbox.core.http.OkHttp3Requestor;
+import com.dropbox.core.oauth.DbxCredential;
+import com.dropbox.core.v2.DbxClientV2;
+import java.net.Proxy;
+import okhttp3.Credentials;
+import okhttp3.OkHttpClient;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.dropbox.credentials.service.DropboxCredentialDetails;
+import org.apache.nifi.dropbox.credentials.service.DropboxCredentialService;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.proxy.ProxyConfiguration;
+
+public interface DropboxTrait {
+
+ PropertyDescriptor CREDENTIAL_SERVICE = new PropertyDescriptor.Builder()
+ .name("dropbox-credential-service")
+ .displayName("Dropbox Credential Service")
+ .description("Controller Service used to obtain Dropbox
credentials (App Key, App Secret, Access Token, Refresh Token)." +
+ " See controller service's Additional Details for more
information.")
+ .identifiesControllerService(DropboxCredentialService.class)
+ .required(true)
+ .build();
+
+
+ default DbxClientV2 getDropboxApiClient(ProcessContext context,
ProxyConfiguration proxyConfiguration, String clientId) {
+ OkHttpClient.Builder okHttpClientBuilder =
OkHttp3Requestor.defaultOkHttpClientBuilder();
+
+ if (!Proxy.Type.DIRECT.equals(proxyConfiguration.getProxyType())) {
+ okHttpClientBuilder.proxy(proxyConfiguration.createProxy());
+
+ if (proxyConfiguration.hasCredential()) {
+ okHttpClientBuilder.proxyAuthenticator((route, response) -> {
+ final String credential =
Credentials.basic(proxyConfiguration.getProxyUserName(),
proxyConfiguration.getProxyUserPassword());
+ return response.request().newBuilder()
+ .header("Proxy-Authorization", credential)
+ .build();
+ });
+ }
+ }
+
+ HttpRequestor httpRequestor = new
OkHttp3Requestor(okHttpClientBuilder.build());
+ DbxRequestConfig config = DbxRequestConfig.newBuilder(clientId)
+ .withHttpRequestor(httpRequestor)
+ .build();
+
+ final DropboxCredentialService credentialService =
context.getProperty(CREDENTIAL_SERVICE)
+ .asControllerService(DropboxCredentialService.class);
+ DropboxCredentialDetails credential =
credentialService.getDropboxCredential();
+
+ return new DbxClientV2(config, new
DbxCredential(credential.getAccessToken(), -1L,
+ credential.getRefreshToken(), credential.getAppKey(),
credential.getAppSecret()));
+ }
+}
diff --git
a/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/main/java/org/apache/nifi/processors/dropbox/FetchDropbox.java
b/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/main/java/org/apache/nifi/processors/dropbox/FetchDropbox.java
new file mode 100644
index 0000000000..3f8c235b0e
--- /dev/null
+++
b/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/main/java/org/apache/nifi/processors/dropbox/FetchDropbox.java
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.processors.dropbox;
+
+import static java.lang.String.format;
+
+import com.dropbox.core.DbxException;
+import com.dropbox.core.v2.DbxClientV2;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+import org.apache.nifi.annotation.behavior.InputRequirement;
+import org.apache.nifi.annotation.behavior.WritesAttribute;
+import org.apache.nifi.annotation.behavior.WritesAttributes;
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.SeeAlso;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnScheduled;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.expression.ExpressionLanguageScope;
+import org.apache.nifi.flowfile.FlowFile;
+import org.apache.nifi.processor.AbstractProcessor;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.processor.ProcessSession;
+import org.apache.nifi.processor.Relationship;
+import org.apache.nifi.processor.exception.ProcessException;
+import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.proxy.ProxyConfiguration;
+import org.apache.nifi.proxy.ProxySpec;
+
+@InputRequirement(InputRequirement.Requirement.INPUT_REQUIRED)
+@Tags({"dropbox", "storage", "fetch"})
+@CapabilityDescription("Fetches files from Dropbox. Designed to be used in
tandem with ListDropbox.")
+@WritesAttribute(attribute = "error.message", description = "When a FlowFile
is routed to 'failure', this attribute is added indicating why the file could "
+ + "not be fetched from Dropbox.")
+@SeeAlso(ListDropbox.class)
+@WritesAttributes(
+ @WritesAttribute(attribute = FetchDropbox.ERROR_MESSAGE_ATTRIBUTE,
description = "The error message returned by Dropbox when the fetch of a file
fails."))
+public class FetchDropbox extends AbstractProcessor implements DropboxTrait {
+
+ public static final String ERROR_MESSAGE_ATTRIBUTE = "error.message";
+
+ public static final PropertyDescriptor FILE = new PropertyDescriptor
+ .Builder().name("file")
+ .displayName("File")
+ .description("The Dropbox identifier or path of the Dropbox file
to fetch." +
+ " The 'File' should match the following regular expression
pattern: /.*|id:.* ." +
+ " When ListDropbox is used for input, either
'${dropbox.id}' (identifying files by Dropbox id)" +
+ " or '${path}/${filename}' (identifying files by path) can
be used as 'File' value.")
+ .required(true)
+ .defaultValue("${dropbox.id}")
+
.expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
+ .addValidator(StandardValidators.createRegexMatchingValidator(
+ Pattern.compile("/.*|id:.*")))
+ .build();
+
+ public static final Relationship REL_SUCCESS =
+ new Relationship.Builder()
+ .name("success")
+ .description("A FlowFile will be routed here for each
successfully fetched File.")
+ .build();
+
+ public static final Relationship REL_FAILURE =
+ new Relationship.Builder().name("failure")
+ .description("A FlowFile will be routed here for each File
for which fetch was attempted but failed.")
+ .build();
+
+ public static final Set<Relationship> relationships =
Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
+ REL_SUCCESS,
+ REL_FAILURE
+ )));
+
+ private static final List<PropertyDescriptor> PROPERTIES =
Collections.unmodifiableList(Arrays.asList(
+ CREDENTIAL_SERVICE,
+ FILE,
+ ProxyConfiguration.createProxyConfigPropertyDescriptor(false,
ProxySpec.HTTP_AUTH)
+ ));
+
+ private DbxClientV2 dropboxApiClient;
+
+ @Override
+ public Set<Relationship> getRelationships() {
+ return relationships;
+ }
+
+ @Override
+ protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
+ return PROPERTIES;
+ }
+
+ @OnScheduled
+ public void onScheduled(final ProcessContext context) {
+ final ProxyConfiguration proxyConfiguration =
ProxyConfiguration.getConfiguration(context);
+ String dropboxClientId = format("%s-%s", getClass().getSimpleName(),
getIdentifier());
+ dropboxApiClient = getDropboxApiClient(context, proxyConfiguration,
dropboxClientId);
+ }
+
+ @Override
+ public void onTrigger(ProcessContext context, ProcessSession session)
throws ProcessException {
+ FlowFile flowFile = session.get();
+ if (flowFile == null) {
+ return;
+ }
+
+ String fileIdentifier =
context.getProperty(FILE).evaluateAttributeExpressions(flowFile).getValue();
+ fileIdentifier = correctFilePath(fileIdentifier);
+
+ FlowFile outFlowFile = flowFile;
+ try {
+ fetchFile(fileIdentifier, session, outFlowFile);
+ session.transfer(outFlowFile, REL_SUCCESS);
+ } catch (Exception e) {
+ handleError(session, flowFile, fileIdentifier, e);
+ }
+ }
+
+ private void fetchFile(String fileId, ProcessSession session, FlowFile
outFlowFile) throws DbxException {
+ InputStream dropboxInputStream = dropboxApiClient.files()
+ .download(fileId)
+ .getInputStream();
+ session.importFrom(dropboxInputStream, outFlowFile);
+ }
+
+ private void handleError(ProcessSession session, FlowFile flowFile, String
fileId, Exception e) {
+ getLogger().error("Error while fetching and processing file with id
'{}'", fileId, e);
+ FlowFile outFlowFile = session.putAttribute(flowFile,
ERROR_MESSAGE_ATTRIBUTE, e.getMessage());
+ session.transfer(outFlowFile, REL_FAILURE);
+ }
+
+ private String correctFilePath(String folderName) {
+ return folderName.startsWith("//") ? folderName.replaceFirst("//",
"/") : folderName;
+ }
+}
diff --git
a/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/main/java/org/apache/nifi/processors/dropbox/ListDropbox.java
b/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/main/java/org/apache/nifi/processors/dropbox/ListDropbox.java
index 2c1b19fe40..18d0a90d85 100644
---
a/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/main/java/org/apache/nifi/processors/dropbox/ListDropbox.java
+++
b/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/main/java/org/apache/nifi/processors/dropbox/ListDropbox.java
@@ -20,8 +20,6 @@ import static java.lang.String.format;
import static java.util.stream.Collectors.toList;
import com.dropbox.core.DbxException;
-import com.dropbox.core.DbxRequestConfig;
-import com.dropbox.core.oauth.DbxCredential;
import com.dropbox.core.v2.DbxClientV2;
import com.dropbox.core.v2.files.FileMetadata;
import com.dropbox.core.v2.files.ListFolderBuilder;
@@ -45,25 +43,26 @@ import org.apache.nifi.annotation.behavior.TriggerSerially;
import org.apache.nifi.annotation.behavior.WritesAttribute;
import org.apache.nifi.annotation.behavior.WritesAttributes;
import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.SeeAlso;
import org.apache.nifi.annotation.documentation.Tags;
import org.apache.nifi.annotation.lifecycle.OnScheduled;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.components.state.Scope;
import org.apache.nifi.context.PropertyContext;
-import org.apache.nifi.dropbox.credentials.service.DropboxCredentialDetails;
-import org.apache.nifi.dropbox.credentials.service.DropboxCredentialService;
import org.apache.nifi.expression.ExpressionLanguageScope;
import org.apache.nifi.processor.ProcessContext;
import org.apache.nifi.processor.util.StandardValidators;
import org.apache.nifi.processor.util.list.AbstractListProcessor;
import org.apache.nifi.processor.util.list.ListedEntityTracker;
+import org.apache.nifi.proxy.ProxyConfiguration;
+import org.apache.nifi.proxy.ProxySpec;
import org.apache.nifi.serialization.record.RecordSchema;
@PrimaryNodeOnly
@TriggerSerially
@Tags({"dropbox", "storage"})
@CapabilityDescription("Retrieves a listing of files from Dropbox (shortcuts
are ignored)." +
- " Each listed file may result in one FlowFile, the metadata being
written as Flowfile attributes." +
+ " Each listed file may result in one FlowFile, the metadata being
written as FlowFile attributes." +
" When the 'Record Writer' property is set, the entire result is
written as records to a single FlowFile." +
" This Processor is designed to run on Primary Node only in a cluster.
If the primary node changes, the new Primary Node will pick up where the" +
" previous node left off without duplicating all of the data.")
@@ -76,8 +75,8 @@ import org.apache.nifi.serialization.record.RecordSchema;
@WritesAttribute(attribute = DropboxFileInfo.REVISION, description =
"Revision of the file")})
@Stateful(scopes = {Scope.CLUSTER}, description = "The processor stores
necessary data to be able to keep track what files have been listed already. " +
"What exactly needs to be stored depends on the 'Listing Strategy'.")
-public class ListDropbox extends AbstractListProcessor<DropboxFileInfo> {
-
+@SeeAlso(FetchDropbox.class)
+public class ListDropbox extends AbstractListProcessor<DropboxFileInfo>
implements DropboxTrait {
public static final PropertyDescriptor FOLDER = new
PropertyDescriptor.Builder()
.name("folder")
.displayName("Folder")
@@ -109,15 +108,6 @@ public class ListDropbox extends
AbstractListProcessor<DropboxFileInfo> {
.defaultValue("0 sec")
.build();
- public static final PropertyDescriptor CREDENTIAL_SERVICE = new
PropertyDescriptor.Builder()
- .name("dropbox-credential-service")
- .displayName("Dropbox Credential Service")
- .description("Controller Service used to obtain Dropbox
credentials (App Key, App Secret, Access Token, Refresh Token)." +
- " See controller service's Additional Details for more
information.")
- .identifiesControllerService(DropboxCredentialService.class)
- .required(true)
- .build();
-
public static final PropertyDescriptor LISTING_STRATEGY = new
PropertyDescriptor.Builder()
.fromPropertyDescriptor(AbstractListProcessor.LISTING_STRATEGY)
.allowableValues(BY_TIMESTAMPS, BY_ENTITIES, BY_TIME_WINDOW,
NO_TRACKING)
@@ -147,14 +137,17 @@ public class ListDropbox extends
AbstractListProcessor<DropboxFileInfo> {
TRACKING_STATE_CACHE,
TRACKING_TIME_WINDOW,
INITIAL_LISTING_TARGET,
- RECORD_WRITER
+ RECORD_WRITER,
+ ProxyConfiguration.createProxyConfigPropertyDescriptor(false,
ProxySpec.HTTP_AUTH)
));
private DbxClientV2 dropboxApiClient;
@OnScheduled
public void onScheduled(final ProcessContext context) {
- dropboxApiClient = getDropboxApiClient(context);
+ final ProxyConfiguration proxyConfiguration =
ProxyConfiguration.getConfiguration(context);
+ String dropboxClientId = format("%s-%s", getClass().getSimpleName(),
getIdentifier());
+ dropboxApiClient = getDropboxApiClient(context, proxyConfiguration,
dropboxClientId);
}
@Override
@@ -181,15 +174,6 @@ public class ListDropbox extends
AbstractListProcessor<DropboxFileInfo> {
return
context.getProperty(FOLDER).evaluateAttributeExpressions().getValue();
}
- protected DbxClientV2 getDropboxApiClient(ProcessContext context) {
- final DropboxCredentialService credentialService =
context.getProperty(CREDENTIAL_SERVICE)
- .asControllerService(DropboxCredentialService.class);
- DbxRequestConfig config = new DbxRequestConfig(format("%s-%s",
getClass().getSimpleName(), getIdentifier()));
- DropboxCredentialDetails credential =
credentialService.getDropboxCredential();
- return new DbxClientV2(config, new
DbxCredential(credential.getAccessToken(), -1L,
- credential.getRefreshToken(), credential.getAppKey(),
credential.getAppSecret()));
- }
-
@Override
protected List<DropboxFileInfo> performListing(ProcessContext context,
Long minTimestamp,
ListingMode listingMode) throws IOException {
diff --git
a/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/main/resources/META-INF/services/org.apache.nifi.processor.Processor
b/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/main/resources/META-INF/services/org.apache.nifi.processor.Processor
index ab3ec13b23..3496b3318e 100644
---
a/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/main/resources/META-INF/services/org.apache.nifi.processor.Processor
+++
b/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/main/resources/META-INF/services/org.apache.nifi.processor.Processor
@@ -13,3 +13,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
org.apache.nifi.processors.dropbox.ListDropbox
+org.apache.nifi.processors.dropbox.FetchDropbox
diff --git
a/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/test/java/org/apache/nifi/processors/dropbox/AbstractDropboxIT.java
b/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/test/java/org/apache/nifi/processors/dropbox/AbstractDropboxIT.java
index 346116035a..4dca22f473 100644
---
a/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/test/java/org/apache/nifi/processors/dropbox/AbstractDropboxIT.java
+++
b/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/test/java/org/apache/nifi/processors/dropbox/AbstractDropboxIT.java
@@ -99,9 +99,9 @@ public abstract class AbstractDropboxIT<T extends Processor> {
}
}
- protected FileMetadata createFile(String name, String fileContent, String
folder) throws Exception {
+ protected FileMetadata createFile(String folder, String filename, String
fileContent) throws Exception {
ByteArrayInputStream content = new
ByteArrayInputStream(fileContent.getBytes(StandardCharsets.UTF_8));
- return client.files().upload(folder + "/" +
name).uploadAndFinish(content);
+ return client.files().upload(folder.equals("/") ? "/" + filename :
folder + "/" + filename).uploadAndFinish(content);
}
private String createFolder(String path) throws Exception {
diff --git
a/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/test/java/org/apache/nifi/processors/dropbox/FetchDropboxIT.java
b/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/test/java/org/apache/nifi/processors/dropbox/FetchDropboxIT.java
new file mode 100644
index 0000000000..8f854e4a89
--- /dev/null
+++
b/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/test/java/org/apache/nifi/processors/dropbox/FetchDropboxIT.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.nifi.processors.dropbox;
+
+import com.dropbox.core.v2.files.FileMetadata;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.nifi.util.MockFlowFile;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class FetchDropboxIT extends AbstractDropboxIT<FetchDropbox> {
+
+ private static final String DEFAULT_FILE_CONTENT = "test_file_content1";
+
+ @BeforeEach
+ public void init() throws Exception {
+ super.init();
+ }
+
+ @Override
+ protected FetchDropbox createTestSubject() {
+ return new FetchDropbox();
+ }
+
+ @Test
+ void testFetchFileById() throws Exception {
+ FileMetadata file = createFile("/testFolder", "test_file1",
DEFAULT_FILE_CONTENT);
+
+ Map<String, String> inputFlowFileAttributes = new HashMap<>();
+ inputFlowFileAttributes.put("dropbox.id", file.getId());
+
+ testRunner.enqueue("unimportant_data", inputFlowFileAttributes);
+ testRunner.run();
+
+ testRunner.assertTransferCount(FetchDropbox.REL_FAILURE, 0);
+ testRunner.assertTransferCount(FetchDropbox.REL_SUCCESS, 1);
+
+ MockFlowFile flowFile =
testRunner.getFlowFilesForRelationship(FetchDropbox.REL_SUCCESS).get(0);
+ flowFile.assertContentEquals(DEFAULT_FILE_CONTENT);
+ }
+
+ @Test
+ void testFetchFileByPath() throws Exception {
+ createFile("/testFolder", "test_file1", DEFAULT_FILE_CONTENT);
+
+ Map<String, String> inputFlowFileAttributes = new HashMap<>();
+ inputFlowFileAttributes.put("path", "/testFolder");
+ inputFlowFileAttributes.put("filename", "test_file1");
+
+ testRunner.setProperty(FetchDropbox.FILE, "${path}/${filename}");
+
+ testRunner.enqueue("unimportant_data", inputFlowFileAttributes);
+ testRunner.run();
+
+ testRunner.assertTransferCount(FetchDropbox.REL_FAILURE, 0);
+ testRunner.assertTransferCount(FetchDropbox.REL_SUCCESS, 1);
+ List<MockFlowFile> flowFiles =
testRunner.getFlowFilesForRelationship(FetchDropbox.REL_SUCCESS);
+ MockFlowFile ff0 = flowFiles.get(0);
+ ff0.assertContentEquals(DEFAULT_FILE_CONTENT);
+ }
+
+ @Test
+ void testFetchFileFromRootByPath() throws Exception {
+ createFile("/", "test_file1", DEFAULT_FILE_CONTENT);
+
+ Map<String, String> inputFlowFileAttributes = new HashMap<>();
+ inputFlowFileAttributes.put("path", "/");
+ inputFlowFileAttributes.put("filename", "test_file1");
+
+ testRunner.setProperty(FetchDropbox.FILE, "${path}/${filename}");
+
+ testRunner.enqueue("unimportant_data", inputFlowFileAttributes);
+ testRunner.run();
+
+ testRunner.assertTransferCount(FetchDropbox.REL_FAILURE, 0);
+ testRunner.assertTransferCount(FetchDropbox.REL_SUCCESS, 1);
+ List<MockFlowFile> flowFiles =
testRunner.getFlowFilesForRelationship(FetchDropbox.REL_SUCCESS);
+ MockFlowFile ff0 = flowFiles.get(0);
+ ff0.assertContentEquals(DEFAULT_FILE_CONTENT);
+ }
+
+ @Test
+ void testFetchingFolderFails() {
+ Map<String, String> inputFlowFileAttributes = new HashMap<>();
+ inputFlowFileAttributes.put("path", "/testFolder");
+
+ testRunner.setProperty(FetchDropbox.FILE, "${path}");
+
+ testRunner.enqueue("unimportant_data", inputFlowFileAttributes);
+ testRunner.run();
+
+ testRunner.assertTransferCount(FetchDropbox.REL_FAILURE, 1);
+ testRunner.assertTransferCount(FetchDropbox.REL_SUCCESS, 0);
+
+ List<MockFlowFile> flowFiles =
testRunner.getFlowFilesForRelationship(FetchDropbox.REL_FAILURE);
+ MockFlowFile ff0 = flowFiles.get(0);
+ ff0.assertAttributeEquals("error.message", "Exception in
2/files/download: {\".tag\":\"path\",\"path\":\"not_file\"}");
+ }
+
+ @Test
+ void testFetchingFileByWrongIdFails() {
+ Map<String, String> inputFlowFileAttributes = new HashMap<>();
+ inputFlowFileAttributes.put("dropbox.id", "id:missing");
+
+ testRunner.enqueue("unimportant_data", inputFlowFileAttributes);
+ testRunner.run();
+
+ testRunner.assertTransferCount(FetchDropbox.REL_SUCCESS, 0);
+ testRunner.assertTransferCount(FetchDropbox.REL_FAILURE, 1);
+
+ List<MockFlowFile> flowFiles =
testRunner.getFlowFilesForRelationship(FetchDropbox.REL_FAILURE);
+ MockFlowFile ff0 = flowFiles.get(0);
+ ff0.assertAttributeEquals("error.message", "Exception in
2/files/download: {\".tag\":\"path\",\"path\":\"not_found\"}");
+ }
+}
diff --git
a/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/test/java/org/apache/nifi/processors/dropbox/FetchDropboxTest.java
b/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/test/java/org/apache/nifi/processors/dropbox/FetchDropboxTest.java
new file mode 100644
index 0000000000..bb4bb9537b
--- /dev/null
+++
b/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/test/java/org/apache/nifi/processors/dropbox/FetchDropboxTest.java
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.processors.dropbox;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.mockito.Mockito.when;
+
+import com.dropbox.core.DbxDownloader;
+import com.dropbox.core.DbxException;
+import com.dropbox.core.v2.DbxClientV2;
+import com.dropbox.core.v2.files.DbxUserFilesRequests;
+import com.dropbox.core.v2.files.FileMetadata;
+import java.io.ByteArrayInputStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.nifi.dropbox.credentials.service.DropboxCredentialService;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.proxy.ProxyConfiguration;
+import org.apache.nifi.reporting.InitializationException;
+import org.apache.nifi.util.MockFlowFile;
+import org.apache.nifi.util.TestRunner;
+import org.apache.nifi.util.TestRunners;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+@ExtendWith(MockitoExtension.class)
+public class FetchDropboxTest {
+
+ public static final String FILE_ID_1 = "id:odTlUvbpIEAAAAAAAAAGGQ";
+ public static final String FILE_ID_2 = "id:odTlUvbpIEBBBBBBBBBGGQ";
+ public static final String FILENAME = "file_name";
+ public static final String FOLDER = "/testFolder";
+ public static final String SIZE = "125";
+ public static final String CREATED_TIME = "1659707000";
+ public static final String REVISION = "5e4ddb1320676a5c29261";
+
+ private TestRunner testRunner;
+
+ @Mock
+ private DbxClientV2 mockDropboxClient;
+
+ @Mock
+ private DropboxCredentialService credentialService;
+
+ @Mock
+ private DbxUserFilesRequests mockDbxUserFilesRequest;
+
+
+ @Mock
+ private DbxDownloader<FileMetadata> mockDbxDownloader;
+
+ @BeforeEach
+ void setUp() throws Exception {
+ FetchDropbox testSubject = new FetchDropbox() {
+ @Override
+ public DbxClientV2 getDropboxApiClient(ProcessContext context,
ProxyConfiguration proxyConfiguration, String clientId) {
+ return mockDropboxClient;
+ }
+ };
+
+ testRunner = TestRunners.newTestRunner(testSubject);
+
+ when(mockDropboxClient.files()).thenReturn(mockDbxUserFilesRequest);
+
+ mockStandardDropboxCredentialService();
+ }
+
+ @Test
+ void testFileIsDownloadedById() throws Exception {
+
+ testRunner.setProperty(FetchDropbox.FILE, "${dropbox.id}");
+
+
when(mockDbxUserFilesRequest.download(FILE_ID_1)).thenReturn(mockDbxDownloader);
+ when(mockDbxDownloader.getInputStream()).thenReturn(new
ByteArrayInputStream("content".getBytes(UTF_8)));
+
+ MockFlowFile inputFlowFile = getMockFlowFile(FILE_ID_1);
+ testRunner.enqueue(inputFlowFile);
+ testRunner.run();
+
+ testRunner.assertAllFlowFilesTransferred(FetchDropbox.REL_SUCCESS, 1);
+ List<MockFlowFile> flowFiles =
testRunner.getFlowFilesForRelationship(FetchDropbox.REL_SUCCESS);
+ MockFlowFile ff0 = flowFiles.get(0);
+ ff0.assertContentEquals("content");
+ assertOutFlowFileAttributes(ff0, FILE_ID_1);
+ }
+
+ @Test
+ void testFileIsDownloadedByPath() throws Exception {
+ testRunner.setProperty(FetchDropbox.FILE, "${path}/${filename}");
+
+ when(mockDbxUserFilesRequest.download(FOLDER + "/" +
FILENAME)).thenReturn(mockDbxDownloader);
+ when(mockDbxDownloader.getInputStream()).thenReturn(new
ByteArrayInputStream("contentByPath".getBytes(UTF_8)));
+
+ MockFlowFile inputFlowFile = getMockFlowFile(FILE_ID_1);
+ testRunner.enqueue(inputFlowFile);
+ testRunner.run();
+
+ testRunner.assertAllFlowFilesTransferred(FetchDropbox.REL_SUCCESS, 1);
+ List<MockFlowFile> flowFiles =
testRunner.getFlowFilesForRelationship(FetchDropbox.REL_SUCCESS);
+ MockFlowFile ff0 = flowFiles.get(0);
+ ff0.assertContentEquals("contentByPath");
+ assertOutFlowFileAttributes(ff0, FILE_ID_1);
+ }
+
+ @Test
+ void testFetchFails() throws Exception {
+ testRunner.setProperty(FetchDropbox.FILE, "${dropbox.id}");
+
+ when(mockDbxUserFilesRequest.download(FILE_ID_2)).thenThrow(new
DbxException("Error in Dropbox"));
+
+ MockFlowFile inputFlowFile = getMockFlowFile(FILE_ID_2);
+ testRunner.enqueue(inputFlowFile);
+ testRunner.run();
+
+ testRunner.assertAllFlowFilesTransferred(FetchDropbox.REL_FAILURE, 1);
+ List<MockFlowFile> flowFiles =
testRunner.getFlowFilesForRelationship(FetchDropbox.REL_FAILURE);
+ MockFlowFile ff0 = flowFiles.get(0);
+ ff0.assertAttributeEquals("error.message", "Error in Dropbox");
+ assertOutFlowFileAttributes(ff0, FILE_ID_2);
+ }
+
+ private void mockStandardDropboxCredentialService() throws
InitializationException {
+ String credentialServiceId = "dropbox_credentials";
+
when(credentialService.getIdentifier()).thenReturn(credentialServiceId);
+ testRunner.addControllerService(credentialServiceId,
credentialService);
+ testRunner.enableControllerService(credentialService);
+ testRunner.setProperty(FetchDropbox.CREDENTIAL_SERVICE,
credentialServiceId);
+ }
+
+ private MockFlowFile getMockFlowFile(String fileId) {
+ MockFlowFile inputFlowFile = new MockFlowFile(0);
+ Map<String, String> attributes = new HashMap<>();
+ attributes.put(DropboxFileInfo.ID, fileId);
+ attributes.put(DropboxFileInfo.REVISION, REVISION);
+ attributes.put(DropboxFileInfo.FILENAME, FILENAME);
+ attributes.put(DropboxFileInfo.PATH, FOLDER);
+ attributes.put(DropboxFileInfo.SIZE, SIZE);
+ attributes.put(DropboxFileInfo.TIMESTAMP, CREATED_TIME);
+ inputFlowFile.putAttributes(attributes);
+ return inputFlowFile;
+ }
+
+ private void assertOutFlowFileAttributes(MockFlowFile flowFile, String
fileId) {
+ flowFile.assertAttributeEquals(DropboxFileInfo.ID, fileId);
+ flowFile.assertAttributeEquals(DropboxFileInfo.REVISION, REVISION);
+ flowFile.assertAttributeEquals(DropboxFileInfo.PATH, FOLDER);
+ flowFile.assertAttributeEquals(DropboxFileInfo.SIZE, SIZE);
+ flowFile.assertAttributeEquals(DropboxFileInfo.TIMESTAMP,
CREATED_TIME);
+ flowFile.assertAttributeEquals(DropboxFileInfo.FILENAME, FILENAME);
+ }
+}
diff --git
a/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/test/java/org/apache/nifi/processors/dropbox/ListDropboxIT.java
b/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/test/java/org/apache/nifi/processors/dropbox/ListDropboxIT.java
index d027f23a5c..0d6658e886 100644
---
a/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/test/java/org/apache/nifi/processors/dropbox/ListDropboxIT.java
+++
b/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/test/java/org/apache/nifi/processors/dropbox/ListDropboxIT.java
@@ -53,12 +53,12 @@ public class ListDropboxIT extends
AbstractDropboxIT<ListDropbox> {
@Test
void testEmbeddedDirectoriesAreListed() throws Exception {
- createFile("test_file1", "test_file_content1", MAIN_FOLDER);
- createFile("test_file2", "test_file_content2", MAIN_FOLDER);
- createFile("test_file11", "test_file_content11", MAIN_FOLDER +
"/testFolder1");
- createFile("test_file112", "test_file_content112", MAIN_FOLDER +
"/testFolder2");
+ createFile(MAIN_FOLDER, "test_file1", "test_file_content1");
+ createFile(MAIN_FOLDER, "test_file2", "test_file_content2");
+ createFile(MAIN_FOLDER + "/testFolder1", "test_file11",
"test_file_content11");
+ createFile(MAIN_FOLDER + "/testFolder2", "test_file112",
"test_file_content112");
- createFile("test_file_not_in_main_folder", "test_file_content31",
NOT_MAIN_FOLDER);
+ createFile(NOT_MAIN_FOLDER, "test_file_not_in_main_folder",
"test_file_content31");
List<String> expectedFileNames = Arrays.asList("test_file1",
"test_file2", "test_file11", "test_file112");
@@ -77,8 +77,8 @@ public class ListDropboxIT extends
AbstractDropboxIT<ListDropbox> {
void testFolderIsListedById() throws Exception {
testRunner.setProperty(ListDropbox.FOLDER, mainFolderId);
- createFile("test_file1", "test_file_content1", MAIN_FOLDER);
- createFile("test_file11", "test_file_content11", MAIN_FOLDER +
"/testFolder1");
+ createFile(MAIN_FOLDER, "test_file1", "test_file_content1");
+ createFile(MAIN_FOLDER + "/testFolder1", "test_file11",
"test_file_content11");
List<String> expectedFileNames = Arrays.asList("test_file1",
"test_file11");
@@ -97,7 +97,7 @@ public class ListDropboxIT extends
AbstractDropboxIT<ListDropbox> {
void testTooYoungFilesNotListedWhenMinAgeIsSet() throws Exception {
testRunner.setProperty(ListDropbox.MIN_AGE, "15 s");
- createFile(YOUNG_FILE_NAME, "test_file_content1", MAIN_FOLDER);
+ createFile(MAIN_FOLDER, YOUNG_FILE_NAME, "test_file_content1");
waitForFileCreation();
diff --git
a/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/test/java/org/apache/nifi/processors/dropbox/ListDropboxTest.java
b/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/test/java/org/apache/nifi/processors/dropbox/ListDropboxTest.java
index 33899936c4..bdabbf9600 100644
---
a/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/test/java/org/apache/nifi/processors/dropbox/ListDropboxTest.java
+++
b/nifi-nar-bundles/nifi-dropbox-bundle/nifi-dropbox-processors/src/test/java/org/apache/nifi/processors/dropbox/ListDropboxTest.java
@@ -20,10 +20,6 @@ package org.apache.nifi.processors.dropbox;
import static java.util.Collections.singletonList;
import static java.util.Spliterators.spliteratorUnknownSize;
import static java.util.stream.Collectors.toList;
-import static
org.apache.nifi.services.dropbox.StandardDropboxCredentialService.ACCESS_TOKEN;
-import static
org.apache.nifi.services.dropbox.StandardDropboxCredentialService.APP_KEY;
-import static
org.apache.nifi.services.dropbox.StandardDropboxCredentialService.APP_SECRET;
-import static
org.apache.nifi.services.dropbox.StandardDropboxCredentialService.REFRESH_TOKEN;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
@@ -45,11 +41,12 @@ import java.util.Date;
import java.util.List;
import java.util.Spliterator;
import java.util.stream.StreamSupport;
+import org.apache.nifi.dropbox.credentials.service.DropboxCredentialService;
import org.apache.nifi.json.JsonRecordSetWriter;
import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.proxy.ProxyConfiguration;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.serialization.RecordSetWriterFactory;
-import org.apache.nifi.services.dropbox.StandardDropboxCredentialService;
import org.apache.nifi.util.MockFlowFile;
import org.apache.nifi.util.TestRunner;
import org.apache.nifi.util.TestRunners;
@@ -79,7 +76,7 @@ public class ListDropboxTest {
private DbxClientV2 mockDropboxClient;
@Mock
- private StandardDropboxCredentialService credentialService;
+ private DropboxCredentialService credentialService;
@Mock
private DbxUserFilesRequests mockDbxUserFilesRequest;
@@ -94,7 +91,7 @@ public class ListDropboxTest {
void setUp() throws Exception {
ListDropbox testSubject = new ListDropbox() {
@Override
- public DbxClientV2 getDropboxApiClient(ProcessContext context) {
+ public DbxClientV2 getDropboxApiClient(ProcessContext context,
ProxyConfiguration proxyConfiguration, String clientId) {
return mockDropboxClient;
}
@@ -143,7 +140,7 @@ public class ListDropboxTest {
//root is listed when "" is used in Dropbox API
when(mockDbxUserFilesRequest.listFolderBuilder("")).thenReturn(mockListFolderBuilder);
when(mockListFolderResult.getEntries()).thenReturn(singletonList(
- createFileMetaData(FILENAME_1, folderName, ID_1, CREATED_TIME)
+ createFileMetadata(FILENAME_1, folderName, ID_1, CREATED_TIME)
));
testRunner.run();
@@ -155,15 +152,16 @@ public class ListDropboxTest {
}
@Test
- void testOnlyFilesAreListedFolderIsFiltered() throws Exception {
+ void testOnlyFilesAreListedFoldersAndShortcutsAreFiltered() throws
Exception {
mockFileListing();
testRunner.setProperty(ListDropbox.FOLDER, TEST_FOLDER);
when(mockDbxUserFilesRequest.listFolderBuilder(TEST_FOLDER)).thenReturn(mockListFolderBuilder);
when(mockListFolderResult.getEntries()).thenReturn(Arrays.asList(
- createFileMetaData(FILENAME_1, TEST_FOLDER, ID_1,
CREATED_TIME),
- createFolderMetaData("testFolder1", TEST_FOLDER)
+ createFileMetadata(FILENAME_1, TEST_FOLDER, ID_1,
CREATED_TIME),
+ createFolderMetadata("testFolder1", TEST_FOLDER),
+ createFileMetadata(FILENAME_2, TEST_FOLDER, ID_2,
CREATED_TIME, false)
));
testRunner.run();
@@ -182,8 +180,8 @@ public class ListDropboxTest {
when(mockDbxUserFilesRequest.listFolderBuilder(TEST_FOLDER)).thenReturn(mockListFolderBuilder);
when(mockListFolderResult.getEntries()).thenReturn(Arrays.asList(
- createFileMetaData(FILENAME_1, TEST_FOLDER, ID_1,
CREATED_TIME),
- createFileMetaData(FILENAME_2, TEST_FOLDER, ID_2,
OLD_CREATED_TIME)
+ createFileMetadata(FILENAME_1, TEST_FOLDER, ID_1,
CREATED_TIME),
+ createFileMetadata(FILENAME_2, TEST_FOLDER, ID_2,
OLD_CREATED_TIME)
));
testRunner.run();
@@ -203,8 +201,8 @@ public class ListDropboxTest {
when(mockDbxUserFilesRequest.listFolderBuilder(TEST_FOLDER)).thenReturn(mockListFolderBuilder);
when(mockListFolderResult.getEntries()).thenReturn(Arrays.asList(
- createFileMetaData(FILENAME_1, TEST_FOLDER, ID_1,
CREATED_TIME),
- createFileMetaData(FILENAME_2, TEST_FOLDER, ID_2, CREATED_TIME)
+ createFileMetadata(FILENAME_1, TEST_FOLDER, ID_1,
CREATED_TIME),
+ createFileMetadata(FILENAME_2, TEST_FOLDER, ID_2, CREATED_TIME)
));
testRunner.run();
@@ -227,20 +225,30 @@ public class ListDropboxTest {
flowFile.assertAttributeEquals(DropboxFileInfo.REVISION, REVISION);
}
- private FileMetadata createFileMetaData(
+ private FileMetadata createFileMetadata(
String filename,
String parent,
String id,
- long createdTime) {
+ long createdTime,
+ boolean isDownloadable) {
return FileMetadata.newBuilder(filename, id,
new Date(createdTime),
new Date(createdTime),
REVISION, SIZE)
.withPathDisplay(parent + "/" + filename)
+ .withIsDownloadable(isDownloadable)
.build();
}
- private Metadata createFolderMetaData(String folderName, String parent) {
+ private FileMetadata createFileMetadata(
+ String filename,
+ String parent,
+ String id,
+ long createdTime) {
+ return createFileMetadata(filename, parent, id, createdTime, true);
+ }
+
+ private Metadata createFolderMetadata(String folderName, String parent) {
return FolderMetadata.newBuilder(folderName)
.withPathDisplay(parent + "/" + folderName)
.build();
@@ -250,10 +258,6 @@ public class ListDropboxTest {
String credentialServiceId = "dropbox_credentials";
when(credentialService.getIdentifier()).thenReturn(credentialServiceId);
testRunner.addControllerService(credentialServiceId,
credentialService);
- testRunner.setProperty(credentialService, APP_KEY, "appKey");
- testRunner.setProperty(credentialService, APP_SECRET, "appSecret");
- testRunner.setProperty(credentialService, ACCESS_TOKEN, "accessToken");
- testRunner.setProperty(credentialService, REFRESH_TOKEN,
"refreshToken");
testRunner.enableControllerService(credentialService);
testRunner.setProperty(ListDropbox.CREDENTIAL_SERVICE,
credentialServiceId);
}