embulk-input-marketo-through-proxy 0.6.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/CODEOWNERS +1 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +37 -0
- data/.github/workflows/build.yml +38 -0
- data/.gitignore +14 -0
- data/CHANGELOG.md +178 -0
- data/LICENSE.txt +21 -0
- data/README.md +231 -0
- data/build.gradle +105 -0
- data/config/checkstyle/checkstyle.xml +128 -0
- data/config/checkstyle/default.xml +108 -0
- data/gradle/wrapper/gradle-wrapper.jar +0 -0
- data/gradle/wrapper/gradle-wrapper.properties +6 -0
- data/gradlew +169 -0
- data/gradlew.bat +84 -0
- data/lib/embulk/input/marketo.rb +3 -0
- data/settings.gradle +1 -0
- data/src/main/java/org/embulk/input/marketo/CsvTokenizer.java +695 -0
- data/src/main/java/org/embulk/input/marketo/MarketoInputPlugin.java +15 -0
- data/src/main/java/org/embulk/input/marketo/MarketoInputPluginDelegate.java +100 -0
- data/src/main/java/org/embulk/input/marketo/MarketoService.java +47 -0
- data/src/main/java/org/embulk/input/marketo/MarketoServiceImpl.java +258 -0
- data/src/main/java/org/embulk/input/marketo/MarketoUtils.java +212 -0
- data/src/main/java/org/embulk/input/marketo/delegate/ActivityBulkExtractInputPlugin.java +169 -0
- data/src/main/java/org/embulk/input/marketo/delegate/CampaignInputPlugin.java +48 -0
- data/src/main/java/org/embulk/input/marketo/delegate/CustomObjectInputPlugin.java +124 -0
- data/src/main/java/org/embulk/input/marketo/delegate/CustomObjectResponseMapperBuilder.java +81 -0
- data/src/main/java/org/embulk/input/marketo/delegate/LeadBulkExtractInputPlugin.java +68 -0
- data/src/main/java/org/embulk/input/marketo/delegate/LeadServiceResponseMapperBuilder.java +85 -0
- data/src/main/java/org/embulk/input/marketo/delegate/LeadWithListInputPlugin.java +89 -0
- data/src/main/java/org/embulk/input/marketo/delegate/LeadWithProgramInputPlugin.java +85 -0
- data/src/main/java/org/embulk/input/marketo/delegate/MarketoBaseBulkExtractInputPlugin.java +448 -0
- data/src/main/java/org/embulk/input/marketo/delegate/MarketoBaseInputPluginDelegate.java +160 -0
- data/src/main/java/org/embulk/input/marketo/delegate/ProgramInputPlugin.java +234 -0
- data/src/main/java/org/embulk/input/marketo/exception/MarketoAPIException.java +30 -0
- data/src/main/java/org/embulk/input/marketo/model/BulkExtractRangeHeader.java +26 -0
- data/src/main/java/org/embulk/input/marketo/model/MarketoAccessTokenResponse.java +92 -0
- data/src/main/java/org/embulk/input/marketo/model/MarketoBulkExtractRequest.java +68 -0
- data/src/main/java/org/embulk/input/marketo/model/MarketoError.java +40 -0
- data/src/main/java/org/embulk/input/marketo/model/MarketoField.java +126 -0
- data/src/main/java/org/embulk/input/marketo/model/MarketoResponse.java +82 -0
- data/src/main/java/org/embulk/input/marketo/model/filter/DateRangeFilter.java +40 -0
- data/src/main/java/org/embulk/input/marketo/rest/MarketoBaseRestClient.java +344 -0
- data/src/main/java/org/embulk/input/marketo/rest/MarketoInputStreamResponseEntityReader.java +69 -0
- data/src/main/java/org/embulk/input/marketo/rest/MarketoRESTEndpoint.java +47 -0
- data/src/main/java/org/embulk/input/marketo/rest/MarketoResponseJetty92EntityReader.java +89 -0
- data/src/main/java/org/embulk/input/marketo/rest/MarketoRestClient.java +601 -0
- data/src/main/java/org/embulk/input/marketo/rest/RecordPagingIterable.java +180 -0
- data/src/test/java/org/embulk/input/marketo/MarketoServiceImplTest.java +147 -0
- data/src/test/java/org/embulk/input/marketo/MarketoUtilsTest.java +89 -0
- data/src/test/java/org/embulk/input/marketo/delegate/ActivityBulkExtractInputPluginTest.java +129 -0
- data/src/test/java/org/embulk/input/marketo/delegate/CampaignInputPluginTest.java +73 -0
- data/src/test/java/org/embulk/input/marketo/delegate/CustomObjectInputPluginTest.java +175 -0
- data/src/test/java/org/embulk/input/marketo/delegate/LeadBulkExtractInputPluginTest.java +102 -0
- data/src/test/java/org/embulk/input/marketo/delegate/LeadServiceResponseMapperBuilderTest.java +119 -0
- data/src/test/java/org/embulk/input/marketo/delegate/LeadWithListInputPluginTest.java +132 -0
- data/src/test/java/org/embulk/input/marketo/delegate/LeadWithProgramInputPluginTest.java +134 -0
- data/src/test/java/org/embulk/input/marketo/delegate/MarketoBaseBulkExtractInputPluginTest.java +171 -0
- data/src/test/java/org/embulk/input/marketo/delegate/MarketoBaseInputPluginDelegateTest.java +60 -0
- data/src/test/java/org/embulk/input/marketo/delegate/ProgramInputPluginTest.java +325 -0
- data/src/test/java/org/embulk/input/marketo/rest/MarketoBaseRestClientTest.java +368 -0
- data/src/test/java/org/embulk/input/marketo/rest/MarketoRestClientTest.java +649 -0
- data/src/test/resources/config/activity_bulk_extract_config.yaml +7 -0
- data/src/test/resources/config/custom_object_config.yaml +8 -0
- data/src/test/resources/config/lead_bulk_extract_config.yaml +8 -0
- data/src/test/resources/config/rest_config.yaml +3 -0
- data/src/test/resources/fixtures/activity_extract1.csv +35 -0
- data/src/test/resources/fixtures/activity_extract2.csv +22 -0
- data/src/test/resources/fixtures/activity_types.json +22 -0
- data/src/test/resources/fixtures/all_program_full.json +53 -0
- data/src/test/resources/fixtures/campaign_response.json +38 -0
- data/src/test/resources/fixtures/campaign_response_full.json +102 -0
- data/src/test/resources/fixtures/custom_object_describe.json +124 -0
- data/src/test/resources/fixtures/custom_object_describe_marketo_fields_full.json +22 -0
- data/src/test/resources/fixtures/custom_object_expected.json +66 -0
- data/src/test/resources/fixtures/custom_object_response.json +24 -0
- data/src/test/resources/fixtures/custom_object_response_full.json +23 -0
- data/src/test/resources/fixtures/lead_by_list.json +33 -0
- data/src/test/resources/fixtures/lead_by_program_response.json +47 -0
- data/src/test/resources/fixtures/lead_describe.json +221 -0
- data/src/test/resources/fixtures/lead_describe_expected.json +66 -0
- data/src/test/resources/fixtures/lead_describe_marketo_fields_full.json +518 -0
- data/src/test/resources/fixtures/lead_extract1.csv +11 -0
- data/src/test/resources/fixtures/lead_response_full.json +2402 -0
- data/src/test/resources/fixtures/lead_with_program_full.json +17 -0
- data/src/test/resources/fixtures/leads_extract2.csv +10 -0
- data/src/test/resources/fixtures/list_reponse_full.json +191 -0
- data/src/test/resources/fixtures/lists_response.json +31 -0
- data/src/test/resources/fixtures/program_response.json +71 -0
- metadata +173 -0
@@ -0,0 +1,344 @@
|
|
1
|
+
package org.embulk.input.marketo.rest;
|
2
|
+
|
3
|
+
import com.fasterxml.jackson.databind.ObjectMapper;
|
4
|
+
import com.google.common.annotations.VisibleForTesting;
|
5
|
+
import com.google.common.base.Optional;
|
6
|
+
import com.google.common.collect.ArrayListMultimap;
|
7
|
+
import com.google.common.collect.Multimap;
|
8
|
+
import org.apache.commons.lang3.StringUtils;
|
9
|
+
import org.eclipse.jetty.client.HttpClient;
|
10
|
+
import org.eclipse.jetty.client.HttpProxy;
|
11
|
+
import org.eclipse.jetty.client.HttpResponseException;
|
12
|
+
import org.eclipse.jetty.client.api.ContentProvider;
|
13
|
+
import org.eclipse.jetty.client.api.Request;
|
14
|
+
import org.eclipse.jetty.client.api.Response;
|
15
|
+
import org.eclipse.jetty.client.util.StringContentProvider;
|
16
|
+
import org.eclipse.jetty.http.HttpMethod;
|
17
|
+
import org.embulk.config.ConfigException;
|
18
|
+
import org.embulk.input.marketo.exception.MarketoAPIException;
|
19
|
+
import org.embulk.input.marketo.model.MarketoAccessTokenResponse;
|
20
|
+
import org.embulk.input.marketo.model.MarketoError;
|
21
|
+
import org.embulk.spi.DataException;
|
22
|
+
import org.embulk.spi.Exec;
|
23
|
+
import org.embulk.util.retryhelper.jetty92.Jetty92ResponseReader;
|
24
|
+
import org.embulk.util.retryhelper.jetty92.Jetty92RetryHelper;
|
25
|
+
import org.embulk.util.retryhelper.jetty92.Jetty92SingleRequester;
|
26
|
+
import org.embulk.util.retryhelper.jetty92.StringJetty92ResponseEntityReader;
|
27
|
+
import org.slf4j.Logger;
|
28
|
+
|
29
|
+
import java.io.EOFException;
|
30
|
+
import java.io.IOException;
|
31
|
+
import java.net.SocketTimeoutException;
|
32
|
+
import java.nio.charset.StandardCharsets;
|
33
|
+
import java.util.Map;
|
34
|
+
import java.util.Objects;
|
35
|
+
import java.util.concurrent.ExecutionException;
|
36
|
+
import java.util.concurrent.TimeoutException;
|
37
|
+
|
38
|
+
import static com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS;
|
39
|
+
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
|
40
|
+
|
41
|
+
/**
|
42
|
+
* Marketo base rest client
|
43
|
+
* Created by tai.khuu on 9/7/17.
|
44
|
+
*/
|
45
|
+
public class MarketoBaseRestClient implements AutoCloseable
|
46
|
+
{
|
47
|
+
private static final Logger LOGGER = Exec.getLogger(MarketoBaseRestClient.class);
|
48
|
+
|
49
|
+
private static final String APPLICATION_JSON = "application/json";
|
50
|
+
|
51
|
+
private static final String AUTHORIZATION_HEADER = "Authorization";
|
52
|
+
|
53
|
+
private String identityEndPoint;
|
54
|
+
|
55
|
+
private String clientId;
|
56
|
+
|
57
|
+
private String clientSecret;
|
58
|
+
|
59
|
+
private String accessToken;
|
60
|
+
|
61
|
+
private int marketoLimitIntervalMillis;
|
62
|
+
|
63
|
+
private Jetty92RetryHelper retryHelper;
|
64
|
+
|
65
|
+
protected long readTimeoutMillis;
|
66
|
+
|
67
|
+
private Optional<String> partnerApiKey;
|
68
|
+
|
69
|
+
protected static final ObjectMapper OBJECT_MAPPER = new ObjectMapper().configure(FAIL_ON_UNKNOWN_PROPERTIES, false).configure(ALLOW_UNQUOTED_CONTROL_CHARS, false);
|
70
|
+
|
71
|
+
MarketoBaseRestClient(String identityEndPoint,
|
72
|
+
String clientId,
|
73
|
+
String clientSecret,
|
74
|
+
Optional<String> partnerApiKey,
|
75
|
+
int marketoLimitIntervalMillis,
|
76
|
+
long readTimeoutMillis,
|
77
|
+
Jetty92RetryHelper retryHelper)
|
78
|
+
{
|
79
|
+
this.identityEndPoint = identityEndPoint;
|
80
|
+
this.clientId = clientId;
|
81
|
+
this.clientSecret = clientSecret;
|
82
|
+
this.readTimeoutMillis = readTimeoutMillis;
|
83
|
+
this.retryHelper = retryHelper;
|
84
|
+
this.marketoLimitIntervalMillis = marketoLimitIntervalMillis;
|
85
|
+
this.partnerApiKey = partnerApiKey;
|
86
|
+
}
|
87
|
+
|
88
|
+
private void renewAccessToken()
|
89
|
+
{
|
90
|
+
accessToken = getAccessTokenWithWrappedException();
|
91
|
+
}
|
92
|
+
|
93
|
+
@VisibleForTesting
|
94
|
+
public String getAccessToken()
|
95
|
+
{
|
96
|
+
if (accessToken == null) {
|
97
|
+
synchronized (this) {
|
98
|
+
if (accessToken == null) {
|
99
|
+
accessToken = getAccessTokenWithWrappedException();
|
100
|
+
}
|
101
|
+
}
|
102
|
+
}
|
103
|
+
return accessToken;
|
104
|
+
}
|
105
|
+
|
106
|
+
private String requestAccessToken()
|
107
|
+
{
|
108
|
+
final Multimap<String, String> params = ArrayListMultimap.create();
|
109
|
+
params.put("client_id", clientId);
|
110
|
+
params.put("client_secret", clientSecret);
|
111
|
+
params.put("grant_type", "client_credentials");
|
112
|
+
|
113
|
+
// add partner api key to the request
|
114
|
+
if (partnerApiKey.isPresent()) {
|
115
|
+
LOGGER.info("> Request access_token with partner_id: {}", StringUtils.abbreviate(partnerApiKey.get(), 8));
|
116
|
+
params.put("partner_id", partnerApiKey.get());
|
117
|
+
}
|
118
|
+
|
119
|
+
String response = retryHelper.requestWithRetry(new StringJetty92ResponseEntityReader(readTimeoutMillis), new Jetty92SingleRequester()
|
120
|
+
{
|
121
|
+
@Override
|
122
|
+
public void requestOnce(HttpClient client, Response.Listener responseListener)
|
123
|
+
{
|
124
|
+
if (hasProxySettings()) {
|
125
|
+
LOGGER.info("Applying proxy setting");
|
126
|
+
client.getProxyConfiguration().getProxies().add(getProxy());
|
127
|
+
}
|
128
|
+
|
129
|
+
Request request = client.newRequest(identityEndPoint + MarketoRESTEndpoint.ACCESS_TOKEN.getEndpoint()).method(HttpMethod.GET);
|
130
|
+
for (String key : params.keySet()) {
|
131
|
+
for (String value : params.get(key)) {
|
132
|
+
request.param(key, value);
|
133
|
+
}
|
134
|
+
}
|
135
|
+
request.send(responseListener);
|
136
|
+
}
|
137
|
+
|
138
|
+
@Override
|
139
|
+
protected boolean isResponseStatusToRetry(Response response)
|
140
|
+
{
|
141
|
+
return response.getStatus() == 502;
|
142
|
+
}
|
143
|
+
|
144
|
+
@Override
|
145
|
+
protected boolean isExceptionToRetry(Exception exception)
|
146
|
+
{
|
147
|
+
if (exception instanceof TimeoutException || exception instanceof SocketTimeoutException || exception instanceof EOFException || super.isExceptionToRetry(exception)) {
|
148
|
+
return true;
|
149
|
+
}
|
150
|
+
// unwrap
|
151
|
+
if (exception instanceof ExecutionException || (exception instanceof IOException && exception.getCause() != null)) {
|
152
|
+
return this.toRetry((Exception) exception.getCause());
|
153
|
+
}
|
154
|
+
return false;
|
155
|
+
}
|
156
|
+
});
|
157
|
+
|
158
|
+
MarketoAccessTokenResponse accessTokenResponse;
|
159
|
+
|
160
|
+
try {
|
161
|
+
accessTokenResponse = OBJECT_MAPPER.readValue(response, MarketoAccessTokenResponse.class);
|
162
|
+
}
|
163
|
+
catch (IOException e) {
|
164
|
+
LOGGER.error("Exception when parse access token response", e);
|
165
|
+
throw new DataException("Can't parse access token response");
|
166
|
+
}
|
167
|
+
if (accessTokenResponse.hasError()) {
|
168
|
+
throw new DataException(accessTokenResponse.getErrorDescription());
|
169
|
+
}
|
170
|
+
LOGGER.info("Acquired new access token");
|
171
|
+
return accessTokenResponse.getAccessToken();
|
172
|
+
}
|
173
|
+
|
174
|
+
protected <T> T doGet(final String target, final Map<String, String> headers, final Multimap<String, String> params, Jetty92ResponseReader<T> responseReader)
|
175
|
+
{
|
176
|
+
return doRequestWithWrappedException(target, HttpMethod.GET, headers, params, null, responseReader);
|
177
|
+
}
|
178
|
+
|
179
|
+
protected <T> T doPost(final String target, final Map<String, String> headers, final Multimap<String, String> params, final String content, Jetty92ResponseReader<T> responseReader)
|
180
|
+
{
|
181
|
+
StringContentProvider contentProvider = null;
|
182
|
+
if (content != null) {
|
183
|
+
contentProvider = new StringContentProvider(APPLICATION_JSON, content, StandardCharsets.UTF_8);
|
184
|
+
}
|
185
|
+
return doPost(target, headers, params, responseReader, contentProvider);
|
186
|
+
}
|
187
|
+
|
188
|
+
protected <T> T doPost(final String target, final Map<String, String> headers, final Multimap<String, String> params, Jetty92ResponseReader<T> responseReader, final ContentProvider content)
|
189
|
+
{
|
190
|
+
return doRequestWithWrappedException(target, HttpMethod.POST, headers, params, content, responseReader);
|
191
|
+
}
|
192
|
+
|
193
|
+
private String getAccessTokenWithWrappedException()
|
194
|
+
{
|
195
|
+
try {
|
196
|
+
return requestAccessToken();
|
197
|
+
}
|
198
|
+
catch (Exception e) {
|
199
|
+
if (e instanceof HttpResponseException) {
|
200
|
+
throw new ConfigException(e.getMessage());
|
201
|
+
}
|
202
|
+
if (e.getCause() instanceof HttpResponseException) {
|
203
|
+
throw new ConfigException(e.getCause().getMessage());
|
204
|
+
}
|
205
|
+
throw e;
|
206
|
+
}
|
207
|
+
}
|
208
|
+
|
209
|
+
private <T> T doRequestWithWrappedException(final String target, final HttpMethod method, final Map<String, String> headers, final Multimap<String, String> params, final ContentProvider contentProvider, Jetty92ResponseReader<T> responseReader)
|
210
|
+
{
|
211
|
+
try {
|
212
|
+
return doRequest(target, method, headers, params, contentProvider, responseReader);
|
213
|
+
}
|
214
|
+
catch (Exception e) {
|
215
|
+
if (e instanceof MarketoAPIException || e instanceof HttpResponseException) {
|
216
|
+
throw new DataException(e.getMessage());
|
217
|
+
}
|
218
|
+
if (e.getCause() instanceof MarketoAPIException || e.getCause() instanceof HttpResponseException) {
|
219
|
+
throw new DataException(e.getCause().getMessage());
|
220
|
+
}
|
221
|
+
throw e;
|
222
|
+
}
|
223
|
+
}
|
224
|
+
|
225
|
+
protected <T> T doRequest(final String target, final HttpMethod method, final Map<String, String> headers, final Multimap<String, String> params, final ContentProvider contentProvider, Jetty92ResponseReader<T> responseReader)
|
226
|
+
{
|
227
|
+
return retryHelper.requestWithRetry(responseReader, new Jetty92SingleRequester()
|
228
|
+
{
|
229
|
+
@Override
|
230
|
+
public void requestOnce(HttpClient client, Response.Listener responseListener)
|
231
|
+
{
|
232
|
+
if (hasProxySettings()) {
|
233
|
+
LOGGER.info("Applying proxy setting");
|
234
|
+
client.getProxyConfiguration().getProxies().add(getProxy());
|
235
|
+
}
|
236
|
+
|
237
|
+
Request request = client.newRequest(target).method(method);
|
238
|
+
if (headers != null) {
|
239
|
+
for (String key : headers.keySet()) {
|
240
|
+
request.header(key, headers.get(key));
|
241
|
+
}
|
242
|
+
}
|
243
|
+
request.header(AUTHORIZATION_HEADER, "Bearer " + getAccessToken());
|
244
|
+
if (params != null) {
|
245
|
+
for (String key : params.keySet()) {
|
246
|
+
for (String value : params.get(key)) {
|
247
|
+
request.param(key, value);
|
248
|
+
}
|
249
|
+
}
|
250
|
+
}
|
251
|
+
LOGGER.info("CALLING {} -> {} - params: {}", method, target, params);
|
252
|
+
if (contentProvider != null) {
|
253
|
+
request.content(contentProvider);
|
254
|
+
}
|
255
|
+
request.send(responseListener);
|
256
|
+
}
|
257
|
+
|
258
|
+
@Override
|
259
|
+
protected boolean isResponseStatusToRetry(Response response)
|
260
|
+
{
|
261
|
+
//413 failed job
|
262
|
+
//414 failed job
|
263
|
+
//502 retry
|
264
|
+
return response.getStatus() / 4 != 100;
|
265
|
+
}
|
266
|
+
|
267
|
+
@Override
|
268
|
+
protected boolean isExceptionToRetry(Exception exception)
|
269
|
+
{
|
270
|
+
if (exception instanceof EOFException || exception instanceof TimeoutException || exception instanceof SocketTimeoutException || super.isExceptionToRetry(exception)) {
|
271
|
+
return true;
|
272
|
+
}
|
273
|
+
if (exception instanceof ExecutionException || (exception instanceof IOException && exception.getCause() != null)) {
|
274
|
+
return this.toRetry((Exception) exception.getCause());
|
275
|
+
}
|
276
|
+
if (exception instanceof MarketoAPIException) {
|
277
|
+
//Retry Authenticate Exception
|
278
|
+
MarketoError error = ((MarketoAPIException) exception).getMarketoErrors().get(0);
|
279
|
+
String code = error.getCode();
|
280
|
+
switch (code) {
|
281
|
+
case "602":
|
282
|
+
case "601":
|
283
|
+
LOGGER.info("Access token expired");
|
284
|
+
renewAccessToken();
|
285
|
+
return true;
|
286
|
+
case "606":
|
287
|
+
try {
|
288
|
+
Thread.sleep(marketoLimitIntervalMillis);
|
289
|
+
}
|
290
|
+
catch (InterruptedException e) {
|
291
|
+
LOGGER.error("Encounter exception when waiting for interval limit", e);
|
292
|
+
throw new DataException("Exception when wait for interval limit");
|
293
|
+
}
|
294
|
+
return true;
|
295
|
+
case "604":
|
296
|
+
case "608":
|
297
|
+
case "611":
|
298
|
+
case "615":
|
299
|
+
case "713":
|
300
|
+
case "1029":
|
301
|
+
return true;
|
302
|
+
default:
|
303
|
+
return false;
|
304
|
+
}
|
305
|
+
}
|
306
|
+
return false;
|
307
|
+
}
|
308
|
+
});
|
309
|
+
}
|
310
|
+
|
311
|
+
@Override
|
312
|
+
public void close()
|
313
|
+
{
|
314
|
+
if (retryHelper != null) {
|
315
|
+
retryHelper.close();
|
316
|
+
}
|
317
|
+
}
|
318
|
+
|
319
|
+
private Boolean hasProxySettings()
|
320
|
+
{
|
321
|
+
if (Objects.isNull(System.getenv("embulk_proxy_host"))) {
|
322
|
+
return false;
|
323
|
+
}
|
324
|
+
if (Objects.isNull(System.getenv( "embulk_proxy_port"))) {
|
325
|
+
return false;
|
326
|
+
}
|
327
|
+
return true;
|
328
|
+
}
|
329
|
+
|
330
|
+
private String getProxyHost()
|
331
|
+
{
|
332
|
+
return System.getenv("embulk_proxy_host").toString();
|
333
|
+
}
|
334
|
+
|
335
|
+
private int getProxyPort()
|
336
|
+
{
|
337
|
+
return Integer.parseInt(System.getenv("embulk_proxy_port"));
|
338
|
+
}
|
339
|
+
|
340
|
+
private HttpProxy getProxy(){
|
341
|
+
return new HttpProxy(getProxyHost(), getProxyPort());
|
342
|
+
}
|
343
|
+
|
344
|
+
}
|
@@ -0,0 +1,69 @@
|
|
1
|
+
package org.embulk.input.marketo.rest;
|
2
|
+
|
3
|
+
import com.fasterxml.jackson.core.type.TypeReference;
|
4
|
+
import com.fasterxml.jackson.databind.ObjectMapper;
|
5
|
+
import com.fasterxml.jackson.databind.ObjectReader;
|
6
|
+
import com.fasterxml.jackson.databind.node.ObjectNode;
|
7
|
+
import com.google.common.io.CharStreams;
|
8
|
+
import org.eclipse.jetty.client.api.Response;
|
9
|
+
import org.eclipse.jetty.client.util.InputStreamResponseListener;
|
10
|
+
import org.eclipse.jetty.http.HttpHeader;
|
11
|
+
import org.embulk.input.marketo.exception.MarketoAPIException;
|
12
|
+
import org.embulk.input.marketo.model.MarketoResponse;
|
13
|
+
import org.embulk.util.retryhelper.jetty92.Jetty92ResponseReader;
|
14
|
+
|
15
|
+
import java.io.InputStream;
|
16
|
+
import java.io.InputStreamReader;
|
17
|
+
import java.util.concurrent.TimeUnit;
|
18
|
+
|
19
|
+
/**
|
20
|
+
* Created by tai.khuu on 9/5/17.
|
21
|
+
*/
|
22
|
+
public class MarketoInputStreamResponseEntityReader implements Jetty92ResponseReader<InputStream>
|
23
|
+
{
|
24
|
+
private static final ObjectReader OBJECT_READER = new ObjectMapper().readerFor(new TypeReference<MarketoResponse<ObjectNode>>(){ });
|
25
|
+
|
26
|
+
private InputStreamResponseListener listener;
|
27
|
+
|
28
|
+
private long timeout;
|
29
|
+
|
30
|
+
public MarketoInputStreamResponseEntityReader(long timeout)
|
31
|
+
{
|
32
|
+
this.timeout = timeout;
|
33
|
+
}
|
34
|
+
|
35
|
+
@Override
|
36
|
+
public Response.Listener getListener()
|
37
|
+
{
|
38
|
+
this.listener = new InputStreamResponseListener();
|
39
|
+
return this.listener;
|
40
|
+
}
|
41
|
+
|
42
|
+
@Override
|
43
|
+
public Response getResponse() throws Exception
|
44
|
+
{
|
45
|
+
return this.listener.get(timeout, TimeUnit.MILLISECONDS);
|
46
|
+
}
|
47
|
+
|
48
|
+
@Override
|
49
|
+
public InputStream readResponseContent() throws Exception
|
50
|
+
{
|
51
|
+
if (!getResponse().getHeaders().getField(HttpHeader.CONTENT_TYPE).getValue().equals("text/csv")) {
|
52
|
+
String errorString = readResponseContentInString();
|
53
|
+
|
54
|
+
MarketoResponse<ObjectNode> errorResponse = OBJECT_READER.readValue(errorString);
|
55
|
+
if (!errorResponse.isSuccess()) {
|
56
|
+
throw new MarketoAPIException(errorResponse.getErrors());
|
57
|
+
}
|
58
|
+
}
|
59
|
+
return this.listener.getInputStream();
|
60
|
+
}
|
61
|
+
|
62
|
+
@Override
|
63
|
+
public String readResponseContentInString() throws Exception
|
64
|
+
{
|
65
|
+
try (InputStreamReader inputStreamReader = new InputStreamReader(this.listener.getInputStream())) {
|
66
|
+
return CharStreams.toString(inputStreamReader);
|
67
|
+
}
|
68
|
+
}
|
69
|
+
}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
package org.embulk.input.marketo.rest;
|
2
|
+
|
3
|
+
import org.apache.commons.lang3.text.StrSubstitutor;
|
4
|
+
|
5
|
+
import java.util.Map;
|
6
|
+
|
7
|
+
/**
|
8
|
+
* Created by tai.khuu on 9/5/17.
|
9
|
+
*/
|
10
|
+
public enum MarketoRESTEndpoint
|
11
|
+
{
|
12
|
+
ACCESS_TOKEN("/oauth/token"),
|
13
|
+
CREATE_LEAD_EXTRACT("/bulk/v1/leads/export/create.json"),
|
14
|
+
CREATE_ACTIVITY_EXTRACT("/bulk/v1/activities/export/create.json"),
|
15
|
+
DESCRIBE_LEAD("/rest/v1/leads/describe.json"),
|
16
|
+
START_LEAD_EXPORT_JOB("/bulk/v1/leads/export/${export_id}/enqueue.json"),
|
17
|
+
START_ACTIVITY_EXPORT_JOB("/bulk/v1/activities/export/${export_id}/enqueue.json"),
|
18
|
+
GET_ACTIVITY_EXPORT_STATUS("/bulk/v1/activities/export/${export_id}/status.json"),
|
19
|
+
GET_LEAD_EXPORT_STATUS("/bulk/v1/leads/export/${export_id}/status.json"),
|
20
|
+
GET_LEAD_EXPORT_RESULT("/bulk/v1/leads/export/${export_id}/file.json"),
|
21
|
+
GET_ACTIVITY_EXPORT_RESULT("/bulk/v1/activities/export/${export_id}/file.json"),
|
22
|
+
GET_LISTS("/rest/v1/lists.json"),
|
23
|
+
GET_LEADS_BY_LIST("/rest/v1/lists/${list_id}/leads.json"),
|
24
|
+
GET_PROGRAMS("/rest/asset/v1/programs.json"),
|
25
|
+
GET_LEADS_BY_PROGRAM("/rest/v1/leads/programs/${program_id}.json"),
|
26
|
+
GET_CAMPAIGN("/rest/v1/campaigns.json"),
|
27
|
+
GET_PROGRAMS_BY_TAG("/rest/asset/v1/program/byTag.json"),
|
28
|
+
GET_CUSTOM_OBJECT("/rest/v1/customobjects/${api_name}.json"),
|
29
|
+
GET_CUSTOM_OBJECT_DESCRIBE("/rest/v1/customobjects/${api_name}/describe.json"),
|
30
|
+
GET_ACTIVITY_TYPES("/rest/v1/activities/types.json");
|
31
|
+
private String endpoint;
|
32
|
+
|
33
|
+
MarketoRESTEndpoint(String endpoint)
|
34
|
+
{
|
35
|
+
this.endpoint = endpoint;
|
36
|
+
}
|
37
|
+
|
38
|
+
public String getEndpoint()
|
39
|
+
{
|
40
|
+
return endpoint;
|
41
|
+
}
|
42
|
+
|
43
|
+
public String getEndpoint(Map<String, String> pathParams)
|
44
|
+
{
|
45
|
+
return StrSubstitutor.replace(endpoint, pathParams);
|
46
|
+
}
|
47
|
+
}
|