Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
8224 manish.sha 1
/******************************************************************************* 
2
 *  Copyright 2009 Amazon Services.
3
 *  Licensed under the Apache License, Version 2.0 (the "License"); 
4
 *  
5
 *  You may not use this file except in compliance with the License. 
6
 *  You may obtain a copy of the License at: http://aws.amazon.com/apache2.0
7
 *  This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
8
 *  CONDITIONS OF ANY KIND, either express or implied. See the License for the 
9
 *  specific language governing permissions and limitations under the License.
10
 * ***************************************************************************** 
11
 *
12
 *  Marketplace Web Service Java Library
13
 *  API Version: 2009-01-01
14
 *  Generated: Tue Feb 17 13:31:26 PST 2009 
15
 * 
16
 */
17
 
18
 
19
 
20
package com.amazonaws.mws;
21
 
22
import java.lang.reflect.Method;
23
import java.io.FileInputStream;
24
import java.io.IOException;
25
import java.io.InputStream;
26
import java.io.InputStreamReader;
27
import java.io.OutputStream;
28
import java.io.Reader;
29
import java.io.StringReader;
30
import java.io.UnsupportedEncodingException;
31
import java.net.MalformedURLException;
32
import java.net.URI;
33
import java.net.URISyntaxException;
34
import java.net.URL;
35
import java.net.URLEncoder;
36
import java.security.DigestInputStream;
37
import java.security.DigestOutputStream;
38
import java.security.MessageDigest;
39
import java.security.NoSuchAlgorithmException;
40
import java.security.SignatureException;
41
import java.text.SimpleDateFormat;
42
import java.util.ArrayList;
43
import java.util.Date;
44
import java.util.HashMap;
45
import java.util.Iterator;
46
import java.util.List;
47
import java.util.Map;
48
import java.util.TimeZone;
49
import java.util.TreeMap;
50
import java.util.Map.Entry;
51
import java.util.concurrent.ArrayBlockingQueue;
52
import java.util.concurrent.Callable;
53
import java.util.concurrent.ExecutorService;
54
import java.util.concurrent.Future;
55
import java.util.concurrent.RejectedExecutionHandler;
56
import java.util.concurrent.ThreadFactory;
57
import java.util.concurrent.ThreadPoolExecutor;
58
import java.util.concurrent.TimeUnit;
59
import java.util.concurrent.atomic.AtomicInteger;
60
import java.util.regex.Matcher;
61
import java.util.regex.Pattern;
62
 
63
import javax.crypto.Mac;
64
import javax.crypto.spec.SecretKeySpec;
65
import javax.xml.bind.JAXBContext;
66
import javax.xml.bind.JAXBException;
67
import javax.xml.bind.Unmarshaller;
68
import javax.xml.transform.stream.StreamSource;
69
 
70
 
71
import org.apache.commons.codec.binary.Base64;
72
import org.apache.http.Header;
73
import org.apache.http.message.BasicHeader;
74
import org.apache.http.HttpStatus;
75
import org.apache.http.auth.AuthScope;
76
import org.apache.http.client.methods.HttpPost;
77
import org.apache.http.params.BasicHttpParams;
78
import org.apache.http.client.entity.UrlEncodedFormEntity;
79
import org.apache.http.entity.InputStreamEntity;
80
import org.apache.http.protocol.HTTP;
81
import org.apache.http.NameValuePair;
82
import org.apache.http.HttpResponse;
83
import org.apache.http.message.BasicNameValuePair;
84
import org.apache.http.auth.UsernamePasswordCredentials;
85
import org.apache.http.impl.client.DefaultHttpClient;
86
import org.apache.http.params.CoreProtocolPNames;
87
import org.apache.http.params.HttpConnectionParams;
88
import org.apache.http.HttpHost;
89
import org.apache.http.conn.params.ConnRoutePNames;
90
import org.apache.http.impl.conn.PoolingClientConnectionManager;
91
import org.apache.commons.logging.Log;
92
import org.apache.commons.logging.LogFactory;
93
import org.apache.http.client.HttpClient;
94
import org.apache.http.client.CredentialsProvider;
95
import org.apache.http.impl.client.BasicCredentialsProvider;
96
import org.apache.http.protocol.HttpContext;
97
import org.apache.http.protocol.BasicHttpContext;
98
import org.apache.http.client.protocol.ClientContext;
99
 
100
 
101
 
102
import com.amazonaws.mws.model.CancelFeedSubmissionsRequest;
103
import com.amazonaws.mws.model.CancelFeedSubmissionsResponse;
104
import com.amazonaws.mws.model.CancelReportRequestsRequest;
105
import com.amazonaws.mws.model.CancelReportRequestsResponse;
106
import com.amazonaws.mws.model.ErrorResponse;
107
import com.amazonaws.mws.model.GetFeedSubmissionCountRequest;
108
import com.amazonaws.mws.model.GetFeedSubmissionCountResponse;
109
import com.amazonaws.mws.model.GetFeedSubmissionListByNextTokenRequest;
110
import com.amazonaws.mws.model.GetFeedSubmissionListByNextTokenResponse;
111
import com.amazonaws.mws.model.GetFeedSubmissionListRequest;
112
import com.amazonaws.mws.model.GetFeedSubmissionListResponse;
113
import com.amazonaws.mws.model.GetFeedSubmissionResultRequest;
114
import com.amazonaws.mws.model.GetFeedSubmissionResultResponse;
115
import com.amazonaws.mws.model.GetFeedSubmissionResultResult;
116
import com.amazonaws.mws.model.GetReportCountRequest;
117
import com.amazonaws.mws.model.GetReportCountResponse;
118
import com.amazonaws.mws.model.GetReportListByNextTokenRequest;
119
import com.amazonaws.mws.model.GetReportListByNextTokenResponse;
120
import com.amazonaws.mws.model.GetReportListRequest;
121
import com.amazonaws.mws.model.GetReportListResponse;
122
import com.amazonaws.mws.model.GetReportRequest;
123
import com.amazonaws.mws.model.GetReportRequestCountRequest;
124
import com.amazonaws.mws.model.GetReportRequestCountResponse;
125
import com.amazonaws.mws.model.GetReportRequestListByNextTokenRequest;
126
import com.amazonaws.mws.model.GetReportRequestListByNextTokenResponse;
127
import com.amazonaws.mws.model.GetReportRequestListRequest;
128
import com.amazonaws.mws.model.GetReportRequestListResponse;
129
import com.amazonaws.mws.model.GetReportResponse;
130
import com.amazonaws.mws.model.GetReportResult;
131
import com.amazonaws.mws.model.GetReportScheduleCountRequest;
132
import com.amazonaws.mws.model.GetReportScheduleCountResponse;
133
import com.amazonaws.mws.model.GetReportScheduleListByNextTokenRequest;
134
import com.amazonaws.mws.model.GetReportScheduleListByNextTokenResponse;
135
import com.amazonaws.mws.model.GetReportScheduleListRequest;
136
import com.amazonaws.mws.model.GetReportScheduleListResponse;
137
import com.amazonaws.mws.model.IdList;
138
import com.amazonaws.mws.model.ManageReportScheduleRequest;
139
import com.amazonaws.mws.model.ManageReportScheduleResponse;
140
import com.amazonaws.mws.model.RequestReportRequest;
141
import com.amazonaws.mws.model.RequestReportResponse;
142
import com.amazonaws.mws.model.ResponseMetadata;
143
import com.amazonaws.mws.model.ResponseHeaderMetadata;
144
import com.amazonaws.mws.model.StatusList;
145
import com.amazonaws.mws.model.SubmitFeedRequest;
146
import com.amazonaws.mws.model.SubmitFeedResponse;
147
import com.amazonaws.mws.model.TypeList;
148
import com.amazonaws.mws.model.UpdateReportAcknowledgementsRequest;
149
import com.amazonaws.mws.model.UpdateReportAcknowledgementsResponse;
150
 
151
/**
152
 * The Amazon Marketplace Web Service contain APIs for inventory and order management.
153
 * 
154
 *
155
 *
156
 * MarketplaceWebServiceClient is implementation of MarketplaceWebService based on the
157
 * Apache <a href="http://jakarta.apache.org/commons/httpclient/">HttpClient</a>.
158
 *
159
 */
160
public  class MarketplaceWebServiceClient implements MarketplaceWebService {
161
 
162
    private final Log log = LogFactory.getLog(MarketplaceWebServiceClient.class);
163
 
164
    private String awsAccessKeyId = null;
165
    private String awsSecretAccessKey = null;
166
    private MarketplaceWebServiceConfig config = null;
167
 
168
    private HttpClient httpClient = null;
169
    private CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
170
    private HttpContext httpContext= null;
171
    private ExecutorService asyncExecutor;
172
 
173
    private List<Header> defaultHeaders = new ArrayList<Header>();
174
 
175
    private static JAXBContext  jaxbContext;
176
    private static ThreadLocal<Unmarshaller> unmarshaller;
177
    private static Pattern ERROR_PATTERN_ONE = Pattern.compile(".*\\<RequestId>(.*)\\</RequestId>.*\\<Error>" +
178
            "\\<Code>(.*)\\</Code>\\<Message>(.*)\\</Message>\\</Error>.*(\\<Error>)?.*",
179
            Pattern.MULTILINE | Pattern.DOTALL);
180
    private static Pattern ERROR_PATTERN_TWO = Pattern.compile(".*\\<Error>\\<Code>(.*)\\</Code>\\<Message>(.*)" +
181
            "\\</Message>\\</Error>.*(\\<Error>)?.*\\<RequestID>(.*)\\</RequestID>.*",
182
            Pattern.MULTILINE | Pattern.DOTALL);
183
    private static String DEFAULT_ENCODING = "UTF-8";
184
    /** Initialize JAXBContext and  Unmarshaller **/
185
    static {
186
        try {
187
            jaxbContext = JAXBContext.newInstance("com.amazonaws.mws.model", MarketplaceWebService.class.getClassLoader());
188
        } catch (JAXBException ex) {
189
            throw new ExceptionInInitializerError(ex);
190
        }
191
        unmarshaller = new ThreadLocal<Unmarshaller>() {
192
            @Override
193
            protected synchronized Unmarshaller initialValue() {
194
                try {
195
                    return jaxbContext.createUnmarshaller();
196
                } catch(JAXBException e) {
197
                    throw new ExceptionInInitializerError(e);
198
                }
199
            }
200
        };
201
    }
202
 
203
 
204
    /**
205
     * Constructs MarketplaceWebServiceClient with AWS Access Key ID and AWS Secret Key
206
     *
207
     * @param awsAccessKeyId
208
     *          AWS Access Key ID
209
     * @param awsSecretAccessKey
210
     *          AWS Secret Access Key
211
     */
212
    public  MarketplaceWebServiceClient(
213
        	String awsAccessKeyId,
214
    		String awsSecretAccessKey,
215
    		String applicationName,
216
    		String applicationVersion) {
217
        this(	awsAccessKeyId, awsSecretAccessKey, 
218
        		applicationName, applicationVersion,
219
        		new MarketplaceWebServiceConfig());
220
    }
221
 
222
    /**
223
     * Constructs MarketplaceWebServiceClient with AWS Access Key ID, AWS Secret Key
224
     * and max number of threads to spawn for async operations
225
     *
226
     * @param awsAccessKeyId
227
     *          AWS Access Key ID
228
     * @param awsSecretAccessKey
229
     *          AWS Secret Access Key
230
     * @param maxAsyncThreads
231
     *          Max number of threads to spawn for async operation.
232
     */
233
    public MarketplaceWebServiceClient(
234
    		String awsAccessKeyId, 
235
    		String awsSecretAccessKey,
236
    		String applicationName,
237
    		String applicationVersion, 
238
    		int maxAsyncThreads) {
239
        this(	awsAccessKeyId, awsSecretAccessKey, 
240
        		applicationName, applicationVersion,
241
        		new MarketplaceWebServiceConfig().withMaxAsyncThreads(maxAsyncThreads));
242
    }
243
 
244
 
245
 
246
    /**
247
     * Constructs MarketplaceWebServiceClient with AWS Access Key ID, AWS Secret Key
248
     * and MarketplaceWebServiceConfig. Use MarketplaceWebServiceConfig to pass additional
249
     * configuration that affects how service is being called.
250
     *
251
     * @param awsAccessKeyId
252
     *          AWS Access Key ID
253
     * @param awsSecretAccessKey
254
     *          AWS Secret Access Key
255
     * @param config
256
     *          Additional configuration options
257
     */
258
    @SuppressWarnings("serial")
259
	public  MarketplaceWebServiceClient(
260
    		String awsAccessKeyId,
261
    		String awsSecretAccessKey,
262
    		String applicationName,
263
    		String applicationVersion,
264
            MarketplaceWebServiceConfig config) {
265
        this.awsAccessKeyId = awsAccessKeyId;
266
        this.awsSecretAccessKey = awsSecretAccessKey;
267
        this.config = config;
268
        this.httpClient = configureHttpClient(applicationName, applicationVersion);
269
        this.asyncExecutor = new ThreadPoolExecutor(config.getMaxAsyncThreads(),
270
                config.getMaxAsyncThreads(), 60L, TimeUnit.SECONDS,
271
                new ArrayBlockingQueue<Runnable>(config.getMaxAsyncQueueSize()) {
272
 
273
                    @Override
274
                    public boolean offer(Runnable task) {
275
                        log.debug("Maximum number of concurrent threads reached, queuing task...");
276
                        return super.offer(task);
277
                    }
278
                },
279
                new ThreadFactory() {
280
 
281
                    private final AtomicInteger threadNumber = new AtomicInteger(1);
282
 
283
                    public Thread newThread(Runnable task) {
284
                        Thread thread = new Thread(task, "MarketplaceWebServiceClient-Thread-" +
285
                                threadNumber.getAndIncrement());
286
                        thread.setDaemon(true);
287
                        if (thread.getPriority() != Thread.NORM_PRIORITY) {
288
                            thread.setPriority(Thread.NORM_PRIORITY);
289
                        }
290
                        log.debug("ThreadFactory created new thread: " + thread.getName());
291
                        return thread;
292
                    }
293
                },
294
                new RejectedExecutionHandler() {
295
 
296
                    public void rejectedExecution(Runnable task, ThreadPoolExecutor executor) {
297
                        log.debug("Maximum number of concurrent threads reached, and queue is full. " +
298
                                "Running task in the calling thread..." + Thread.currentThread().getName());
299
                        if (!executor.isShutdown()) {
300
                            task.run();
301
                        }
302
                    }
303
                });
304
    }
305
 
306
    // Public API ------------------------------------------------------------//
307
 
308
 
309
 
310
    /**
311
     * Get Report 
312
     *
313
     * The GetReport operation returns the contents of a report. Reports can potentially be
314
     * very large (>100MB) which is why we only return one report at a time, and in a
315
     * streaming fashion.
316
     * 
317
     * @param request
318
     *          GetReportRequest request
319
     * @return
320
     *          GetReport Response from the service
321
     *
322
     * @throws MarketplaceWebServiceException
323
     */
324
    public GetReportResponse getReport(GetReportRequest request) throws MarketplaceWebServiceException {
325
        return invoke(GetReportResponse.class, convertGetReport(request), request);
326
    }
327
 
328
    /**
329
     * Non-blocking Get Report 
330
     * <p/>
331
     * Returns <code>future</code> pointer to GetReportResponse
332
     * <p/>
333
     * If response is ready, call to <code>future.get()</code> 
334
     * will return GetReportResponse. 
335
     * <p/>
336
     * If response is not ready, call to <code>future.get()</code> will block the 
337
     * calling thread until response is returned. 
338
     * <p/>
339
     * Note, <code>future.get()</code> will throw wrapped runtime exception. 
340
     * <p/>
341
     * If service error has occured, MarketplaceWebServiceException can be extracted with
342
     * <code>exception.getCause()</code>
343
     * <p/>
344
     * Usage example for parallel processing:
345
     * <pre>
346
     *
347
     *  List&lt;Future&lt;GetReportResponse&gt;&gt; responses = new ArrayList&lt;Future&lt;GetReportResponse&gt;&gt;();
348
     *  for (GetReportRequest request : requests) {
349
     *      responses.add(client.getReportAsync(request));
350
     *  }
351
     *  for (Future&lt;GetReportResponse&gt; future : responses) {
352
     *      while (!future.isDone()) {
353
     *          Thread.yield();
354
     *      }
355
     *      try {
356
     *          GetReportResponse response = future.get();
357
     *      // use response
358
     *      } catch (Exception e) {
359
     *          if (e instanceof MarketplaceWebServiceException) {
360
     *              MarketplaceWebServiceException exception = MarketplaceWebServiceException.class.cast(e);
361
     *          // handle MarketplaceWebServiceException
362
     *          } else {
363
     *          // handle other exceptions
364
     *          }
365
     *      }
366
     *  }
367
     * </pre>
368
     *
369
     * @param request
370
     *          GetReportRequest request
371
     * @return Future&lt;GetReportResponse&gt; future pointer to GetReportResponse
372
     * 
373
     */
374
    public Future<GetReportResponse> getReportAsync(final GetReportRequest request) {
375
        Future<GetReportResponse> response = asyncExecutor.submit(new Callable<GetReportResponse>() {
376
 
377
            public GetReportResponse call() throws MarketplaceWebServiceException {
378
                return getReport(request);
379
            }
380
            });
381
        return response;
382
    }
383
 
384
    /**
385
     * Get Report Schedule Count 
386
     *
387
     * returns the number of report schedules
388
     * 
389
     * @param request
390
     *          GetReportScheduleCountRequest request
391
     * @return
392
     *          GetReportScheduleCount Response from the service
393
     *
394
     * @throws MarketplaceWebServiceException
395
     */
396
    public GetReportScheduleCountResponse getReportScheduleCount(GetReportScheduleCountRequest request) throws MarketplaceWebServiceException {
397
        return invoke(GetReportScheduleCountResponse.class, convertGetReportScheduleCount(request));
398
    }
399
 
400
    /**
401
     * Non-blocking Get Report Schedule Count 
402
     * <p/>
403
     * Returns <code>future</code> pointer to GetReportScheduleCountResponse
404
     * <p/>
405
     * If response is ready, call to <code>future.get()</code> 
406
     * will return GetReportScheduleCountResponse. 
407
     * <p/>
408
     * If response is not ready, call to <code>future.get()</code> will block the 
409
     * calling thread until response is returned. 
410
     * <p/>
411
     * Note, <code>future.get()</code> will throw wrapped runtime exception. 
412
     * <p/>
413
     * If service error has occured, MarketplaceWebServiceException can be extracted with
414
     * <code>exception.getCause()</code>
415
     * <p/>
416
     * Usage example for parallel processing:
417
     * <pre>
418
     *
419
     *  List&lt;Future&lt;GetReportScheduleCountResponse&gt;&gt; responses = new ArrayList&lt;Future&lt;GetReportScheduleCountResponse&gt;&gt;();
420
     *  for (GetReportScheduleCountRequest request : requests) {
421
     *      responses.add(client.getReportScheduleCountAsync(request));
422
     *  }
423
     *  for (Future&lt;GetReportScheduleCountResponse&gt; future : responses) {
424
     *      while (!future.isDone()) {
425
     *          Thread.yield();
426
     *      }
427
     *      try {
428
     *          GetReportScheduleCountResponse response = future.get();
429
     *      // use response
430
     *      } catch (Exception e) {
431
     *          if (e instanceof MarketplaceWebServiceException) {
432
     *              MarketplaceWebServiceException exception = MarketplaceWebServiceException.class.cast(e);
433
     *          // handle MarketplaceWebServiceException
434
     *          } else {
435
     *          // handle other exceptions
436
     *          }
437
     *      }
438
     *  }
439
     * </pre>
440
     *
441
     * @param request
442
     *          GetReportScheduleCountRequest request
443
     * @return Future&lt;GetReportScheduleCountResponse&gt; future pointer to GetReportScheduleCountResponse
444
     * 
445
     */
446
    public Future<GetReportScheduleCountResponse> getReportScheduleCountAsync(final GetReportScheduleCountRequest request) {
447
        Future<GetReportScheduleCountResponse> response = asyncExecutor.submit(new Callable<GetReportScheduleCountResponse>() {
448
 
449
            public GetReportScheduleCountResponse call() throws MarketplaceWebServiceException {
450
                return getReportScheduleCount(request);
451
            }
452
            });
453
        return response;
454
    }
455
 
456
    /**
457
     * Get Report Request List By Next Token 
458
     *
459
     * retrieve the next batch of list items and if there are more items to retrieve
460
     * 
461
     * @param request
462
     *          GetReportRequestListByNextTokenRequest request
463
     * @return
464
     *          GetReportRequestListByNextToken Response from the service
465
     *
466
     * @throws MarketplaceWebServiceException
467
     */
468
    public GetReportRequestListByNextTokenResponse getReportRequestListByNextToken(GetReportRequestListByNextTokenRequest request) throws MarketplaceWebServiceException {
469
        return invoke(GetReportRequestListByNextTokenResponse.class, convertGetReportRequestListByNextToken(request));
470
    }
471
 
472
    /**
473
     * Non-blocking Get Report Request List By Next Token 
474
     * <p/>
475
     * Returns <code>future</code> pointer to GetReportRequestListByNextTokenResponse
476
     * <p/>
477
     * If response is ready, call to <code>future.get()</code> 
478
     * will return GetReportRequestListByNextTokenResponse. 
479
     * <p/>
480
     * If response is not ready, call to <code>future.get()</code> will block the 
481
     * calling thread until response is returned. 
482
     * <p/>
483
     * Note, <code>future.get()</code> will throw wrapped runtime exception. 
484
     * <p/>
485
     * If service error has occured, MarketplaceWebServiceException can be extracted with
486
     * <code>exception.getCause()</code>
487
     * <p/>
488
     * Usage example for parallel processing:
489
     * <pre>
490
     *
491
     *  List&lt;Future&lt;GetReportRequestListByNextTokenResponse&gt;&gt; responses = new ArrayList&lt;Future&lt;GetReportRequestListByNextTokenResponse&gt;&gt;();
492
     *  for (GetReportRequestListByNextTokenRequest request : requests) {
493
     *      responses.add(client.getReportRequestListByNextTokenAsync(request));
494
     *  }
495
     *  for (Future&lt;GetReportRequestListByNextTokenResponse&gt; future : responses) {
496
     *      while (!future.isDone()) {
497
     *          Thread.yield();
498
     *      }
499
     *      try {
500
     *          GetReportRequestListByNextTokenResponse response = future.get();
501
     *      // use response
502
     *      } catch (Exception e) {
503
     *          if (e instanceof MarketplaceWebServiceException) {
504
     *              MarketplaceWebServiceException exception = MarketplaceWebServiceException.class.cast(e);
505
     *          // handle MarketplaceWebServiceException
506
     *          } else {
507
     *          // handle other exceptions
508
     *          }
509
     *      }
510
     *  }
511
     * </pre>
512
     *
513
     * @param request
514
     *          GetReportRequestListByNextTokenRequest request
515
     * @return Future&lt;GetReportRequestListByNextTokenResponse&gt; future pointer to GetReportRequestListByNextTokenResponse
516
     * 
517
     */
518
    public Future<GetReportRequestListByNextTokenResponse> getReportRequestListByNextTokenAsync(final GetReportRequestListByNextTokenRequest request) {
519
        Future<GetReportRequestListByNextTokenResponse> response = asyncExecutor.submit(new Callable<GetReportRequestListByNextTokenResponse>() {
520
 
521
            public GetReportRequestListByNextTokenResponse call() throws MarketplaceWebServiceException {
522
                return getReportRequestListByNextToken(request);
523
            }
524
            });
525
        return response;
526
    }
527
 
528
    /**
529
     * Update Report Acknowledgements 
530
     *
531
     * The UpdateReportAcknowledgements operation updates the acknowledged status of one or more reports.
532
     * 
533
     * @param request
534
     *          UpdateReportAcknowledgementsRequest request
535
     * @return
536
     *          UpdateReportAcknowledgements Response from the service
537
     *
538
     * @throws MarketplaceWebServiceException
539
     */
540
    public UpdateReportAcknowledgementsResponse updateReportAcknowledgements(UpdateReportAcknowledgementsRequest request) throws MarketplaceWebServiceException {
541
        return invoke(UpdateReportAcknowledgementsResponse.class, convertUpdateReportAcknowledgements(request));
542
    }
543
 
544
    /**
545
     * Non-blocking Update Report Acknowledgements 
546
     * <p/>
547
     * Returns <code>future</code> pointer to UpdateReportAcknowledgementsResponse
548
     * <p/>
549
     * If response is ready, call to <code>future.get()</code> 
550
     * will return UpdateReportAcknowledgementsResponse. 
551
     * <p/>
552
     * If response is not ready, call to <code>future.get()</code> will block the 
553
     * calling thread until response is returned. 
554
     * <p/>
555
     * Note, <code>future.get()</code> will throw wrapped runtime exception. 
556
     * <p/>
557
     * If service error has occured, MarketplaceWebServiceException can be extracted with
558
     * <code>exception.getCause()</code>
559
     * <p/>
560
     * Usage example for parallel processing:
561
     * <pre>
562
     *
563
     *  List&lt;Future&lt;UpdateReportAcknowledgementsResponse&gt;&gt; responses = new ArrayList&lt;Future&lt;UpdateReportAcknowledgementsResponse&gt;&gt;();
564
     *  for (UpdateReportAcknowledgementsRequest request : requests) {
565
     *      responses.add(client.updateReportAcknowledgementsAsync(request));
566
     *  }
567
     *  for (Future&lt;UpdateReportAcknowledgementsResponse&gt; future : responses) {
568
     *      while (!future.isDone()) {
569
     *          Thread.yield();
570
     *      }
571
     *      try {
572
     *          UpdateReportAcknowledgementsResponse response = future.get();
573
     *      // use response
574
     *      } catch (Exception e) {
575
     *          if (e instanceof MarketplaceWebServiceException) {
576
     *              MarketplaceWebServiceException exception = MarketplaceWebServiceException.class.cast(e);
577
     *          // handle MarketplaceWebServiceException
578
     *          } else {
579
     *          // handle other exceptions
580
     *          }
581
     *      }
582
     *  }
583
     * </pre>
584
     *
585
     * @param request
586
     *          UpdateReportAcknowledgementsRequest request
587
     * @return Future&lt;UpdateReportAcknowledgementsResponse&gt; future pointer to UpdateReportAcknowledgementsResponse
588
     * 
589
     */
590
    public Future<UpdateReportAcknowledgementsResponse> updateReportAcknowledgementsAsync(final UpdateReportAcknowledgementsRequest request) {
591
        Future<UpdateReportAcknowledgementsResponse> response = asyncExecutor.submit(new Callable<UpdateReportAcknowledgementsResponse>() {
592
 
593
            public UpdateReportAcknowledgementsResponse call() throws MarketplaceWebServiceException {
594
                return updateReportAcknowledgements(request);
595
            }
596
            });
597
        return response;
598
    }
599
 
600
    /**
601
     * Submit Feed 
602
     *
603
     * Uploads a file for processing together with the necessary
604
     * metadata to process the file, such as which type of feed it is.
605
     * PurgeAndReplace if true means that your existing e.g. inventory is
606
     * wiped out and replace with the contents of this feed - use with
607
     * caution (the default is false).
608
     * 
609
     * @param request
610
     *          SubmitFeedRequest request
611
     * @return
612
     *          SubmitFeed Response from the service
613
     *
614
     * @throws MarketplaceWebServiceException
615
     */
616
    public SubmitFeedResponse submitFeed(SubmitFeedRequest request) throws MarketplaceWebServiceException {
617
        return invoke(SubmitFeedResponse.class, convertSubmitFeed(request), request);
618
    }
619
 
620
 
621
    /**
622
     * Non-blocking Submit Feed 
623
     * <p/>
624
     * Returns <code>future</code> pointer to SubmitFeedResponse
625
     * <p/>
626
     * If response is ready, call to <code>future.get()</code> 
627
     * will return SubmitFeedResponse. 
628
     * <p/>
629
     * If response is not ready, call to <code>future.get()</code> will block the 
630
     * calling thread until response is returned. 
631
     * <p/>
632
     * Note, <code>future.get()</code> will throw wrapped runtime exception. 
633
     * <p/>
634
     * If service error has occured, MarketplaceWebServiceException can be extracted with
635
     * <code>exception.getCause()</code>
636
     * <p/>
637
     * Usage example for parallel processing:
638
     * <pre>
639
     *
640
     *  List&lt;Future&lt;SubmitFeedResponse&gt;&gt; responses = new ArrayList&lt;Future&lt;SubmitFeedResponse&gt;&gt;();
641
     *  for (SubmitFeedRequest request : requests) {
642
     *      responses.add(client.submitFeedAsync(request));
643
     *  }
644
     *  for (Future&lt;SubmitFeedResponse&gt; future : responses) {
645
     *      while (!future.isDone()) {
646
     *          Thread.yield();
647
     *      }
648
     *      try {
649
     *          SubmitFeedResponse response = future.get();
650
     *      // use response
651
     *      } catch (Exception e) {
652
     *          if (e instanceof MarketplaceWebServiceException) {
653
     *              MarketplaceWebServiceException exception = MarketplaceWebServiceException.class.cast(e);
654
     *          // handle MarketplaceWebServiceException
655
     *          } else {
656
     *          // handle other exceptions
657
     *          }
658
     *      }
659
     *  }
660
     * </pre>
661
     *
662
     * @param request
663
     *          SubmitFeedRequest request
664
     * @return Future&lt;SubmitFeedResponse&gt; future pointer to SubmitFeedResponse
665
     * 
666
     */
667
    public Future<SubmitFeedResponse> submitFeedAsync(final SubmitFeedRequest request) {
668
        Future<SubmitFeedResponse> response = asyncExecutor.submit(new Callable<SubmitFeedResponse>() {
669
 
670
            public SubmitFeedResponse call() throws MarketplaceWebServiceException {
671
                return submitFeed(request);
672
            }
673
            });
674
        return response;
675
    }
676
 
677
    /**
678
     * Submit Feed From File
679
     *
680
     * Uploads a file from disk for processing together with the necessary
681
     * metadata to process the file, such as which type of feed it is.
682
     * PurgeAndReplace if true means that your existing e.g. inventory is
683
     * wiped out and replace with the contents of this feed - use with
684
     * caution (the default is false).
685
     * 
686
     * This function assumes the Content MD5 value is unset in the request, and will
687
     * set it before making the Submit Feed request. The Feed Content must be stored
688
     * on disk, as the assumption is that the content is accessed through
689
     * a FileInputStream.
690
     * 
691
     * @param request
692
     *          SubmitFeedRequest request without the contentMd5 field set.
693
     * @return
694
     *          SubmitFeed Response from the service
695
     *
696
     * @throws MarketplaceWebServiceException
697
     */
698
    public SubmitFeedResponse submitFeedFromFile( SubmitFeedRequest request )
699
      throws MarketplaceWebServiceException {
700
 
701
        try {
702
            String contentMd5 = computeContentMD5HeaderValue( (FileInputStream)request.getFeedContent() );
703
            request.setContentMD5( contentMd5 );
704
        }
705
        catch( Throwable t ) {
706
            throw new MarketplaceWebServiceException( t );
707
        }
708
 
709
        return submitFeed( request );
710
    }
711
 
712
    /**
713
     * Non-blocking Submit Feed From File 
714
     * <p/>
715
     * Returns <code>future</code> pointer to SubmitFeedResponse
716
     * <p/>
717
     * If response is ready, call to <code>future.get()</code> 
718
     * will return SubmitFeedResponse. 
719
     * <p/>
720
     * If response is not ready, call to <code>future.get()</code> will block the 
721
     * calling thread until response is returned. 
722
     * <p/>
723
     * Note, <code>future.get()</code> will throw wrapped runtime exception. 
724
     * <p/>
725
     * If service error has occured, MarketplaceWebServiceException can be extracted with
726
     * <code>exception.getCause()</code>
727
     * <p/>
728
     * Usage example for parallel processing:
729
     * <pre>
730
     *
731
     *  List&lt;Future&lt;SubmitFeedResponse&gt;&gt; responses = new ArrayList&lt;Future&lt;SubmitFeedResponse&gt;&gt;();
732
     *  for (SubmitFeedRequest request : requests) {
733
     *      responses.add(client.submitFeedFromFileAsync(request));
734
     *  }
735
     *  for (Future&lt;SubmitFeedResponse&gt; future : responses) {
736
     *      while (!future.isDone()) {
737
     *          Thread.yield();
738
     *      }
739
     *      try {
740
     *          SubmitFeedResponse response = future.get();
741
     *      // use response
742
     *      } catch (Exception e) {
743
     *          if (e instanceof MarketplaceWebServiceException) {
744
     *              MarketplaceWebServiceException exception = MarketplaceWebServiceException.class.cast(e);
745
     *          // handle MarketplaceWebServiceException
746
     *          } else {
747
     *          // handle other exceptions
748
     *          }
749
     *      }
750
     *  }
751
     * </pre>
752
     *
753
     * @param request
754
     *          SubmitFeedRequest request
755
     * @return Future&lt;SubmitFeedResponse&gt; future pointer to SubmitFeedResponse
756
     * 
757
     */
758
    public Future<SubmitFeedResponse> submitFeedFromFileAsync(final SubmitFeedRequest request) {
759
        Future<SubmitFeedResponse> response = asyncExecutor.submit(new Callable<SubmitFeedResponse>() {
760
 
761
            public SubmitFeedResponse call() throws MarketplaceWebServiceException { 
762
                return submitFeedFromFile( request );
763
            }
764
            });
765
        return response;
766
    }
767
 
768
    /**
769
     * Get Report Count 
770
     *
771
     * returns a count of reports matching your criteria;
772
     * by default, the number of reports generated in the last 90 days,
773
     * regardless of acknowledgment status
774
     * 
775
     * @param request
776
     *          GetReportCountRequest request
777
     * @return
778
     *          GetReportCount Response from the service
779
     *
780
     * @throws MarketplaceWebServiceException
781
     */
782
    public GetReportCountResponse getReportCount(GetReportCountRequest request) throws MarketplaceWebServiceException {
783
        return invoke(GetReportCountResponse.class, convertGetReportCount(request));
784
    }
785
 
786
    /**
787
     * Non-blocking Get Report Count 
788
     * <p/>
789
     * Returns <code>future</code> pointer to GetReportCountResponse
790
     * <p/>
791
     * If response is ready, call to <code>future.get()</code> 
792
     * will return GetReportCountResponse. 
793
     * <p/>
794
     * If response is not ready, call to <code>future.get()</code> will block the 
795
     * calling thread until response is returned. 
796
     * <p/>
797
     * Note, <code>future.get()</code> will throw wrapped runtime exception. 
798
     * <p/>
799
     * If service error has occured, MarketplaceWebServiceException can be extracted with
800
     * <code>exception.getCause()</code>
801
     * <p/>
802
     * Usage example for parallel processing:
803
     * <pre>
804
     *
805
     *  List&lt;Future&lt;GetReportCountResponse&gt;&gt; responses = new ArrayList&lt;Future&lt;GetReportCountResponse&gt;&gt;();
806
     *  for (GetReportCountRequest request : requests) {
807
     *      responses.add(client.getReportCountAsync(request));
808
     *  }
809
     *  for (Future&lt;GetReportCountResponse&gt; future : responses) {
810
     *      while (!future.isDone()) {
811
     *          Thread.yield();
812
     *      }
813
     *      try {
814
     *          GetReportCountResponse response = future.get();
815
     *      // use response
816
     *      } catch (Exception e) {
817
     *          if (e instanceof MarketplaceWebServiceException) {
818
     *              MarketplaceWebServiceException exception = MarketplaceWebServiceException.class.cast(e);
819
     *          // handle MarketplaceWebServiceException
820
     *          } else {
821
     *          // handle other exceptions
822
     *          }
823
     *      }
824
     *  }
825
     * </pre>
826
     *
827
     * @param request
828
     *          GetReportCountRequest request
829
     * @return Future&lt;GetReportCountResponse&gt; future pointer to GetReportCountResponse
830
     * 
831
     */
832
    public Future<GetReportCountResponse> getReportCountAsync(final GetReportCountRequest request) {
833
        Future<GetReportCountResponse> response = asyncExecutor.submit(new Callable<GetReportCountResponse>() {
834
 
835
            public GetReportCountResponse call() throws MarketplaceWebServiceException {
836
                return getReportCount(request);
837
            }
838
            });
839
        return response;
840
    }
841
 
842
    /**
843
     * Get Feed Submission List By Next Token 
844
     *
845
     * retrieve the next batch of list items and if there are more items to retrieve
846
     * 
847
     * @param request
848
     *          GetFeedSubmissionListByNextTokenRequest request
849
     * @return
850
     *          GetFeedSubmissionListByNextToken Response from the service
851
     *
852
     * @throws MarketplaceWebServiceException
853
     */
854
    public GetFeedSubmissionListByNextTokenResponse getFeedSubmissionListByNextToken(GetFeedSubmissionListByNextTokenRequest request) throws MarketplaceWebServiceException {
855
        return invoke(GetFeedSubmissionListByNextTokenResponse.class, convertGetFeedSubmissionListByNextToken(request));
856
    }
857
 
858
    /**
859
     * Non-blocking Get Feed Submission List By Next Token 
860
     * <p/>
861
     * Returns <code>future</code> pointer to GetFeedSubmissionListByNextTokenResponse
862
     * <p/>
863
     * If response is ready, call to <code>future.get()</code> 
864
     * will return GetFeedSubmissionListByNextTokenResponse. 
865
     * <p/>
866
     * If response is not ready, call to <code>future.get()</code> will block the 
867
     * calling thread until response is returned. 
868
     * <p/>
869
     * Note, <code>future.get()</code> will throw wrapped runtime exception. 
870
     * <p/>
871
     * If service error has occured, MarketplaceWebServiceException can be extracted with
872
     * <code>exception.getCause()</code>
873
     * <p/>
874
     * Usage example for parallel processing:
875
     * <pre>
876
     *
877
     *  List&lt;Future&lt;GetFeedSubmissionListByNextTokenResponse&gt;&gt; responses = new ArrayList&lt;Future&lt;GetFeedSubmissionListByNextTokenResponse&gt;&gt;();
878
     *  for (GetFeedSubmissionListByNextTokenRequest request : requests) {
879
     *      responses.add(client.getFeedSubmissionListByNextTokenAsync(request));
880
     *  }
881
     *  for (Future&lt;GetFeedSubmissionListByNextTokenResponse&gt; future : responses) {
882
     *      while (!future.isDone()) {
883
     *          Thread.yield();
884
     *      }
885
     *      try {
886
     *          GetFeedSubmissionListByNextTokenResponse response = future.get();
887
     *      // use response
888
     *      } catch (Exception e) {
889
     *          if (e instanceof MarketplaceWebServiceException) {
890
     *              MarketplaceWebServiceException exception = MarketplaceWebServiceException.class.cast(e);
891
     *          // handle MarketplaceWebServiceException
892
     *          } else {
893
     *          // handle other exceptions
894
     *          }
895
     *      }
896
     *  }
897
     * </pre>
898
     *
899
     * @param request
900
     *          GetFeedSubmissionListByNextTokenRequest request
901
     * @return Future&lt;GetFeedSubmissionListByNextTokenResponse&gt; future pointer to GetFeedSubmissionListByNextTokenResponse
902
     * 
903
     */
904
    public Future<GetFeedSubmissionListByNextTokenResponse> getFeedSubmissionListByNextTokenAsync(final GetFeedSubmissionListByNextTokenRequest request) {
905
        Future<GetFeedSubmissionListByNextTokenResponse> response = asyncExecutor.submit(new Callable<GetFeedSubmissionListByNextTokenResponse>() {
906
 
907
            public GetFeedSubmissionListByNextTokenResponse call() throws MarketplaceWebServiceException {
908
                return getFeedSubmissionListByNextToken(request);
909
            }
910
            });
911
        return response;
912
    }
913
 
914
    /**
915
     * Cancel Feed Submissions 
916
     *
917
     * cancels feed submissions - by default all of the submissions of the
918
     * last 30 days that have not started processing
919
     * 
920
     * @param request
921
     *          CancelFeedSubmissionsRequest request
922
     * @return
923
     *          CancelFeedSubmissions Response from the service
924
     *
925
     * @throws MarketplaceWebServiceException
926
     */
927
    public CancelFeedSubmissionsResponse cancelFeedSubmissions(CancelFeedSubmissionsRequest request) throws MarketplaceWebServiceException {
928
        return invoke(CancelFeedSubmissionsResponse.class, convertCancelFeedSubmissions(request));
929
    }
930
 
931
    /**
932
     * Non-blocking Cancel Feed Submissions 
933
     * <p/>
934
     * Returns <code>future</code> pointer to CancelFeedSubmissionsResponse
935
     * <p/>
936
     * If response is ready, call to <code>future.get()</code> 
937
     * will return CancelFeedSubmissionsResponse. 
938
     * <p/>
939
     * If response is not ready, call to <code>future.get()</code> will block the 
940
     * calling thread until response is returned. 
941
     * <p/>
942
     * Note, <code>future.get()</code> will throw wrapped runtime exception. 
943
     * <p/>
944
     * If service error has occured, MarketplaceWebServiceException can be extracted with
945
     * <code>exception.getCause()</code>
946
     * <p/>
947
     * Usage example for parallel processing:
948
     * <pre>
949
     *
950
     *  List&lt;Future&lt;CancelFeedSubmissionsResponse&gt;&gt; responses = new ArrayList&lt;Future&lt;CancelFeedSubmissionsResponse&gt;&gt;();
951
     *  for (CancelFeedSubmissionsRequest request : requests) {
952
     *      responses.add(client.cancelFeedSubmissionsAsync(request));
953
     *  }
954
     *  for (Future&lt;CancelFeedSubmissionsResponse&gt; future : responses) {
955
     *      while (!future.isDone()) {
956
     *          Thread.yield();
957
     *      }
958
     *      try {
959
     *          CancelFeedSubmissionsResponse response = future.get();
960
     *      // use response
961
     *      } catch (Exception e) {
962
     *          if (e instanceof MarketplaceWebServiceException) {
963
     *              MarketplaceWebServiceException exception = MarketplaceWebServiceException.class.cast(e);
964
     *          // handle MarketplaceWebServiceException
965
     *          } else {
966
     *          // handle other exceptions
967
     *          }
968
     *      }
969
     *  }
970
     * </pre>
971
     *
972
     * @param request
973
     *          CancelFeedSubmissionsRequest request
974
     * @return Future&lt;CancelFeedSubmissionsResponse&gt; future pointer to CancelFeedSubmissionsResponse
975
     * 
976
     */
977
    public Future<CancelFeedSubmissionsResponse> cancelFeedSubmissionsAsync(final CancelFeedSubmissionsRequest request) {
978
        Future<CancelFeedSubmissionsResponse> response = asyncExecutor.submit(new Callable<CancelFeedSubmissionsResponse>() {
979
 
980
            public CancelFeedSubmissionsResponse call() throws MarketplaceWebServiceException {
981
                return cancelFeedSubmissions(request);
982
            }
983
            });
984
        return response;
985
    }
986
 
987
    /**
988
     * Request Report 
989
     *
990
     * requests the generation of a report
991
     * 
992
     * @param request
993
     *          RequestReportRequest request
994
     * @return
995
     *          RequestReport Response from the service
996
     *
997
     * @throws MarketplaceWebServiceException
998
     */
999
    public RequestReportResponse requestReport(RequestReportRequest request) throws MarketplaceWebServiceException {
1000
        return invoke(RequestReportResponse.class, convertRequestReport(request));
1001
    }
1002
 
1003
    /**
1004
     * Non-blocking Request Report 
1005
     * <p/>
1006
     * Returns <code>future</code> pointer to RequestReportResponse
1007
     * <p/>
1008
     * If response is ready, call to <code>future.get()</code> 
1009
     * will return RequestReportResponse. 
1010
     * <p/>
1011
     * If response is not ready, call to <code>future.get()</code> will block the 
1012
     * calling thread until response is returned. 
1013
     * <p/>
1014
     * Note, <code>future.get()</code> will throw wrapped runtime exception. 
1015
     * <p/>
1016
     * If service error has occured, MarketplaceWebServiceException can be extracted with
1017
     * <code>exception.getCause()</code>
1018
     * <p/>
1019
     * Usage example for parallel processing:
1020
     * <pre>
1021
     *
1022
     *  List&lt;Future&lt;RequestReportResponse&gt;&gt; responses = new ArrayList&lt;Future&lt;RequestReportResponse&gt;&gt;();
1023
     *  for (RequestReportRequest request : requests) {
1024
     *      responses.add(client.requestReportAsync(request));
1025
     *  }
1026
     *  for (Future&lt;RequestReportResponse&gt; future : responses) {
1027
     *      while (!future.isDone()) {
1028
     *          Thread.yield();
1029
     *      }
1030
     *      try {
1031
     *          RequestReportResponse response = future.get();
1032
     *      // use response
1033
     *      } catch (Exception e) {
1034
     *          if (e instanceof MarketplaceWebServiceException) {
1035
     *              MarketplaceWebServiceException exception = MarketplaceWebServiceException.class.cast(e);
1036
     *          // handle MarketplaceWebServiceException
1037
     *          } else {
1038
     *          // handle other exceptions
1039
     *          }
1040
     *      }
1041
     *  }
1042
     * </pre>
1043
     *
1044
     * @param request
1045
     *          RequestReportRequest request
1046
     * @return Future&lt;RequestReportResponse&gt; future pointer to RequestReportResponse
1047
     * 
1048
     */
1049
    public Future<RequestReportResponse> requestReportAsync(final RequestReportRequest request) {
1050
        Future<RequestReportResponse> response = asyncExecutor.submit(new Callable<RequestReportResponse>() {
1051
 
1052
            public RequestReportResponse call() throws MarketplaceWebServiceException {
1053
                return requestReport(request);
1054
            }
1055
            });
1056
        return response;
1057
    }
1058
 
1059
    /**
1060
     * Get Feed Submission Count 
1061
     *
1062
     * returns the number of feeds matching all of the specified criteria
1063
     * 
1064
     * @param request
1065
     *          GetFeedSubmissionCountRequest request
1066
     * @return
1067
     *          GetFeedSubmissionCount Response from the service
1068
     *
1069
     * @throws MarketplaceWebServiceException
1070
     */
1071
    public GetFeedSubmissionCountResponse getFeedSubmissionCount(GetFeedSubmissionCountRequest request) throws MarketplaceWebServiceException {
1072
        return invoke(GetFeedSubmissionCountResponse.class, convertGetFeedSubmissionCount(request));
1073
    }
1074
 
1075
    /**
1076
     * Non-blocking Get Feed Submission Count 
1077
     * <p/>
1078
     * Returns <code>future</code> pointer to GetFeedSubmissionCountResponse
1079
     * <p/>
1080
     * If response is ready, call to <code>future.get()</code> 
1081
     * will return GetFeedSubmissionCountResponse. 
1082
     * <p/>
1083
     * If response is not ready, call to <code>future.get()</code> will block the 
1084
     * calling thread until response is returned. 
1085
     * <p/>
1086
     * Note, <code>future.get()</code> will throw wrapped runtime exception. 
1087
     * <p/>
1088
     * If service error has occured, MarketplaceWebServiceException can be extracted with
1089
     * <code>exception.getCause()</code>
1090
     * <p/>
1091
     * Usage example for parallel processing:
1092
     * <pre>
1093
     *
1094
     *  List&lt;Future&lt;GetFeedSubmissionCountResponse&gt;&gt; responses = new ArrayList&lt;Future&lt;GetFeedSubmissionCountResponse&gt;&gt;();
1095
     *  for (GetFeedSubmissionCountRequest request : requests) {
1096
     *      responses.add(client.getFeedSubmissionCountAsync(request));
1097
     *  }
1098
     *  for (Future&lt;GetFeedSubmissionCountResponse&gt; future : responses) {
1099
     *      while (!future.isDone()) {
1100
     *          Thread.yield();
1101
     *      }
1102
     *      try {
1103
     *          GetFeedSubmissionCountResponse response = future.get();
1104
     *      // use response
1105
     *      } catch (Exception e) {
1106
     *          if (e instanceof MarketplaceWebServiceException) {
1107
     *              MarketplaceWebServiceException exception = MarketplaceWebServiceException.class.cast(e);
1108
     *          // handle MarketplaceWebServiceException
1109
     *          } else {
1110
     *          // handle other exceptions
1111
     *          }
1112
     *      }
1113
     *  }
1114
     * </pre>
1115
     *
1116
     * @param request
1117
     *          GetFeedSubmissionCountRequest request
1118
     * @return Future&lt;GetFeedSubmissionCountResponse&gt; future pointer to GetFeedSubmissionCountResponse
1119
     * 
1120
     */
1121
    public Future<GetFeedSubmissionCountResponse> getFeedSubmissionCountAsync(final GetFeedSubmissionCountRequest request) {
1122
        Future<GetFeedSubmissionCountResponse> response = asyncExecutor.submit(new Callable<GetFeedSubmissionCountResponse>() {
1123
 
1124
            public GetFeedSubmissionCountResponse call() throws MarketplaceWebServiceException {
1125
                return getFeedSubmissionCount(request);
1126
            }
1127
            });
1128
        return response;
1129
    }
1130
 
1131
    /**
1132
     * Cancel Report Requests 
1133
     *
1134
     * cancels report request that have not yet started processing,
1135
     * by default all those within the last 90 days
1136
     * 
1137
     * @param request
1138
     *          CancelReportRequestsRequest request
1139
     * @return
1140
     *          CancelReportRequests Response from the service
1141
     *
1142
     * @throws MarketplaceWebServiceException
1143
     */
1144
    public CancelReportRequestsResponse cancelReportRequests(CancelReportRequestsRequest request) throws MarketplaceWebServiceException {
1145
        return invoke(CancelReportRequestsResponse.class, convertCancelReportRequests(request));
1146
    }
1147
 
1148
    /**
1149
     * Non-blocking Cancel Report Requests 
1150
     * <p/>
1151
     * Returns <code>future</code> pointer to CancelReportRequestsResponse
1152
     * <p/>
1153
     * If response is ready, call to <code>future.get()</code> 
1154
     * will return CancelReportRequestsResponse. 
1155
     * <p/>
1156
     * If response is not ready, call to <code>future.get()</code> will block the 
1157
     * calling thread until response is returned. 
1158
     * <p/>
1159
     * Note, <code>future.get()</code> will throw wrapped runtime exception. 
1160
     * <p/>
1161
     * If service error has occured, MarketplaceWebServiceException can be extracted with
1162
     * <code>exception.getCause()</code>
1163
     * <p/>
1164
     * Usage example for parallel processing:
1165
     * <pre>
1166
     *
1167
     *  List&lt;Future&lt;CancelReportRequestsResponse&gt;&gt; responses = new ArrayList&lt;Future&lt;CancelReportRequestsResponse&gt;&gt;();
1168
     *  for (CancelReportRequestsRequest request : requests) {
1169
     *      responses.add(client.cancelReportRequestsAsync(request));
1170
     *  }
1171
     *  for (Future&lt;CancelReportRequestsResponse&gt; future : responses) {
1172
     *      while (!future.isDone()) {
1173
     *          Thread.yield();
1174
     *      }
1175
     *      try {
1176
     *          CancelReportRequestsResponse response = future.get();
1177
     *      // use response
1178
     *      } catch (Exception e) {
1179
     *          if (e instanceof MarketplaceWebServiceException) {
1180
     *              MarketplaceWebServiceException exception = MarketplaceWebServiceException.class.cast(e);
1181
     *          // handle MarketplaceWebServiceException
1182
     *          } else {
1183
     *          // handle other exceptions
1184
     *          }
1185
     *      }
1186
     *  }
1187
     * </pre>
1188
     *
1189
     * @param request
1190
     *          CancelReportRequestsRequest request
1191
     * @return Future&lt;CancelReportRequestsResponse&gt; future pointer to CancelReportRequestsResponse
1192
     * 
1193
     */
1194
    public Future<CancelReportRequestsResponse> cancelReportRequestsAsync(final CancelReportRequestsRequest request) {
1195
        Future<CancelReportRequestsResponse> response = asyncExecutor.submit(new Callable<CancelReportRequestsResponse>() {
1196
 
1197
            public CancelReportRequestsResponse call() throws MarketplaceWebServiceException {
1198
                return cancelReportRequests(request);
1199
            }
1200
            });
1201
        return response;
1202
    }
1203
 
1204
    /**
1205
     * Get Report List 
1206
     *
1207
     * returns a list of reports; by default the most recent ten reports,
1208
     * regardless of their acknowledgment status
1209
     * 
1210
     * @param request
1211
     *          GetReportListRequest request
1212
     * @return
1213
     *          GetReportList Response from the service
1214
     *
1215
     * @throws MarketplaceWebServiceException
1216
     */
1217
    public GetReportListResponse getReportList(GetReportListRequest request) throws MarketplaceWebServiceException {
1218
        return invoke(GetReportListResponse.class, convertGetReportList(request));
1219
    }
1220
 
1221
    /**
1222
     * Non-blocking Get Report List 
1223
     * <p/>
1224
     * Returns <code>future</code> pointer to GetReportListResponse
1225
     * <p/>
1226
     * If response is ready, call to <code>future.get()</code> 
1227
     * will return GetReportListResponse. 
1228
     * <p/>
1229
     * If response is not ready, call to <code>future.get()</code> will block the 
1230
     * calling thread until response is returned. 
1231
     * <p/>
1232
     * Note, <code>future.get()</code> will throw wrapped runtime exception. 
1233
     * <p/>
1234
     * If service error has occured, MarketplaceWebServiceException can be extracted with
1235
     * <code>exception.getCause()</code>
1236
     * <p/>
1237
     * Usage example for parallel processing:
1238
     * <pre>
1239
     *
1240
     *  List&lt;Future&lt;GetReportListResponse&gt;&gt; responses = new ArrayList&lt;Future&lt;GetReportListResponse&gt;&gt;();
1241
     *  for (GetReportListRequest request : requests) {
1242
     *      responses.add(client.getReportListAsync(request));
1243
     *  }
1244
     *  for (Future&lt;GetReportListResponse&gt; future : responses) {
1245
     *      while (!future.isDone()) {
1246
     *          Thread.yield();
1247
     *      }
1248
     *      try {
1249
     *          GetReportListResponse response = future.get();
1250
     *      // use response
1251
     *      } catch (Exception e) {
1252
     *          if (e instanceof MarketplaceWebServiceException) {
1253
     *              MarketplaceWebServiceException exception = MarketplaceWebServiceException.class.cast(e);
1254
     *          // handle MarketplaceWebServiceException
1255
     *          } else {
1256
     *          // handle other exceptions
1257
     *          }
1258
     *      }
1259
     *  }
1260
     * </pre>
1261
     *
1262
     * @param request
1263
     *          GetReportListRequest request
1264
     * @return Future&lt;GetReportListResponse&gt; future pointer to GetReportListResponse
1265
     * 
1266
     */
1267
    public Future<GetReportListResponse> getReportListAsync(final GetReportListRequest request) {
1268
        Future<GetReportListResponse> response = asyncExecutor.submit(new Callable<GetReportListResponse>() {
1269
 
1270
            public GetReportListResponse call() throws MarketplaceWebServiceException {
1271
                return getReportList(request);
1272
            }
1273
            });
1274
        return response;
1275
    }
1276
 
1277
    /**
1278
     * Get Feed Submission Result 
1279
     *
1280
     * retrieves the feed processing report
1281
     * 
1282
     * @param request
1283
     *          GetFeedSubmissionResultRequest request
1284
     * @return
1285
     *          GetFeedSubmissionResult Response from the service
1286
     *
1287
     * @throws MarketplaceWebServiceException
1288
     */
1289
    public GetFeedSubmissionResultResponse getFeedSubmissionResult(GetFeedSubmissionResultRequest request) throws MarketplaceWebServiceException {
1290
        return invoke(GetFeedSubmissionResultResponse.class, convertGetFeedSubmissionResult(request), request);
1291
    }
1292
 
1293
    /**
1294
     * Non-blocking Get Feed Submission Result 
1295
     * <p/>
1296
     * Returns <code>future</code> pointer to GetFeedSubmissionResultResponse
1297
     * <p/>
1298
     * If response is ready, call to <code>future.get()</code> 
1299
     * will return GetFeedSubmissionResultResponse. 
1300
     * <p/>
1301
     * If response is not ready, call to <code>future.get()</code> will block the 
1302
     * calling thread until response is returned. 
1303
     * <p/>
1304
     * Note, <code>future.get()</code> will throw wrapped runtime exception. 
1305
     * <p/>
1306
     * If service error has occured, MarketplaceWebServiceException can be extracted with
1307
     * <code>exception.getCause()</code>
1308
     * <p/>
1309
     * Usage example for parallel processing:
1310
     * <pre>
1311
     *
1312
     *  List&lt;Future&lt;GetFeedSubmissionResultResponse&gt;&gt; responses = new ArrayList&lt;Future&lt;GetFeedSubmissionResultResponse&gt;&gt;();
1313
     *  for (GetFeedSubmissionResultRequest request : requests) {
1314
     *      responses.add(client.getFeedSubmissionResultAsync(request));
1315
     *  }
1316
     *  for (Future&lt;GetFeedSubmissionResultResponse&gt; future : responses) {
1317
     *      while (!future.isDone()) {
1318
     *          Thread.yield();
1319
     *      }
1320
     *      try {
1321
     *          GetFeedSubmissionResultResponse response = future.get();
1322
     *      // use response
1323
     *      } catch (Exception e) {
1324
     *          if (e instanceof MarketplaceWebServiceException) {
1325
     *              MarketplaceWebServiceException exception = MarketplaceWebServiceException.class.cast(e);
1326
     *          // handle MarketplaceWebServiceException
1327
     *          } else {
1328
     *          // handle other exceptions
1329
     *          }
1330
     *      }
1331
     *  }
1332
     * </pre>
1333
     *
1334
     * @param request
1335
     *          GetFeedSubmissionResultRequest request
1336
     * @return Future&lt;GetFeedSubmissionResultResponse&gt; future pointer to GetFeedSubmissionResultResponse
1337
     * 
1338
     */
1339
    public Future<GetFeedSubmissionResultResponse> getFeedSubmissionResultAsync(final GetFeedSubmissionResultRequest request) {
1340
        Future<GetFeedSubmissionResultResponse> response = asyncExecutor.submit(new Callable<GetFeedSubmissionResultResponse>() {
1341
 
1342
            public GetFeedSubmissionResultResponse call() throws MarketplaceWebServiceException {
1343
                return getFeedSubmissionResult(request);
1344
            }
1345
            });
1346
        return response;
1347
    }
1348
 
1349
    /**
1350
     * Get Feed Submission List 
1351
     *
1352
     * returns a list of feed submission identifiers and their associated metadata
1353
     * 
1354
     * @param request
1355
     *          GetFeedSubmissionListRequest request
1356
     * @return
1357
     *          GetFeedSubmissionList Response from the service
1358
     *
1359
     * @throws MarketplaceWebServiceException
1360
     */
1361
    public GetFeedSubmissionListResponse getFeedSubmissionList(GetFeedSubmissionListRequest request) throws MarketplaceWebServiceException {
1362
        return invoke(GetFeedSubmissionListResponse.class, convertGetFeedSubmissionList(request));
1363
    }
1364
 
1365
    /**
1366
     * Non-blocking Get Feed Submission List 
1367
     * <p/>
1368
     * Returns <code>future</code> pointer to GetFeedSubmissionListResponse
1369
     * <p/>
1370
     * If response is ready, call to <code>future.get()</code> 
1371
     * will return GetFeedSubmissionListResponse. 
1372
     * <p/>
1373
     * If response is not ready, call to <code>future.get()</code> will block the 
1374
     * calling thread until response is returned. 
1375
     * <p/>
1376
     * Note, <code>future.get()</code> will throw wrapped runtime exception. 
1377
     * <p/>
1378
     * If service error has occured, MarketplaceWebServiceException can be extracted with
1379
     * <code>exception.getCause()</code>
1380
     * <p/>
1381
     * Usage example for parallel processing:
1382
     * <pre>
1383
     *
1384
     *  List&lt;Future&lt;GetFeedSubmissionListResponse&gt;&gt; responses = new ArrayList&lt;Future&lt;GetFeedSubmissionListResponse&gt;&gt;();
1385
     *  for (GetFeedSubmissionListRequest request : requests) {
1386
     *      responses.add(client.getFeedSubmissionListAsync(request));
1387
     *  }
1388
     *  for (Future&lt;GetFeedSubmissionListResponse&gt; future : responses) {
1389
     *      while (!future.isDone()) {
1390
     *          Thread.yield();
1391
     *      }
1392
     *      try {
1393
     *          GetFeedSubmissionListResponse response = future.get();
1394
     *      // use response
1395
     *      } catch (Exception e) {
1396
     *          if (e instanceof MarketplaceWebServiceException) {
1397
     *              MarketplaceWebServiceException exception = MarketplaceWebServiceException.class.cast(e);
1398
     *          // handle MarketplaceWebServiceException
1399
     *          } else {
1400
     *          // handle other exceptions
1401
     *          }
1402
     *      }
1403
     *  }
1404
     * </pre>
1405
     *
1406
     * @param request
1407
     *          GetFeedSubmissionListRequest request
1408
     * @return Future&lt;GetFeedSubmissionListResponse&gt; future pointer to GetFeedSubmissionListResponse
1409
     * 
1410
     */
1411
    public Future<GetFeedSubmissionListResponse> getFeedSubmissionListAsync(final GetFeedSubmissionListRequest request) {
1412
        Future<GetFeedSubmissionListResponse> response = asyncExecutor.submit(new Callable<GetFeedSubmissionListResponse>() {
1413
 
1414
            public GetFeedSubmissionListResponse call() throws MarketplaceWebServiceException {
1415
                return getFeedSubmissionList(request);
1416
            }
1417
            });
1418
        return response;
1419
    }
1420
 
1421
    /**
1422
     * Get Report Request List 
1423
     *
1424
     * returns a list of report requests ids and their associated metadata
1425
     * 
1426
     * @param request
1427
     *          GetReportRequestListRequest request
1428
     * @return
1429
     *          GetReportRequestList Response from the service
1430
     *
1431
     * @throws MarketplaceWebServiceException
1432
     */
1433
    public GetReportRequestListResponse getReportRequestList(GetReportRequestListRequest request) throws MarketplaceWebServiceException {
1434
        return invoke(GetReportRequestListResponse.class, convertGetReportRequestList(request));
1435
    }
1436
 
1437
    /**
1438
     * Non-blocking Get Report Request List 
1439
     * <p/>
1440
     * Returns <code>future</code> pointer to GetReportRequestListResponse
1441
     * <p/>
1442
     * If response is ready, call to <code>future.get()</code> 
1443
     * will return GetReportRequestListResponse. 
1444
     * <p/>
1445
     * If response is not ready, call to <code>future.get()</code> will block the 
1446
     * calling thread until response is returned. 
1447
     * <p/>
1448
     * Note, <code>future.get()</code> will throw wrapped runtime exception. 
1449
     * <p/>
1450
     * If service error has occured, MarketplaceWebServiceException can be extracted with
1451
     * <code>exception.getCause()</code>
1452
     * <p/>
1453
     * Usage example for parallel processing:
1454
     * <pre>
1455
     *
1456
     *  List&lt;Future&lt;GetReportRequestListResponse&gt;&gt; responses = new ArrayList&lt;Future&lt;GetReportRequestListResponse&gt;&gt;();
1457
     *  for (GetReportRequestListRequest request : requests) {
1458
     *      responses.add(client.getReportRequestListAsync(request));
1459
     *  }
1460
     *  for (Future&lt;GetReportRequestListResponse&gt; future : responses) {
1461
     *      while (!future.isDone()) {
1462
     *          Thread.yield();
1463
     *      }
1464
     *      try {
1465
     *          GetReportRequestListResponse response = future.get();
1466
     *      // use response
1467
     *      } catch (Exception e) {
1468
     *          if (e instanceof MarketplaceWebServiceException) {
1469
     *              MarketplaceWebServiceException exception = MarketplaceWebServiceException.class.cast(e);
1470
     *          // handle MarketplaceWebServiceException
1471
     *          } else {
1472
     *          // handle other exceptions
1473
     *          }
1474
     *      }
1475
     *  }
1476
     * </pre>
1477
     *
1478
     * @param request
1479
     *          GetReportRequestListRequest request
1480
     * @return Future&lt;GetReportRequestListResponse&gt; future pointer to GetReportRequestListResponse
1481
     * 
1482
     */
1483
    public Future<GetReportRequestListResponse> getReportRequestListAsync(final GetReportRequestListRequest request) {
1484
        Future<GetReportRequestListResponse> response = asyncExecutor.submit(new Callable<GetReportRequestListResponse>() {
1485
 
1486
            public GetReportRequestListResponse call() throws MarketplaceWebServiceException {
1487
                return getReportRequestList(request);
1488
            }
1489
            });
1490
        return response;
1491
    }
1492
 
1493
    /**
1494
     * Get Report Schedule List By Next Token 
1495
     *
1496
     * retrieve the next batch of list items and if there are more items to retrieve
1497
     * 
1498
     * @param request
1499
     *          GetReportScheduleListByNextTokenRequest request
1500
     * @return
1501
     *          GetReportScheduleListByNextToken Response from the service
1502
     *
1503
     * @throws MarketplaceWebServiceException
1504
     */
1505
    public GetReportScheduleListByNextTokenResponse getReportScheduleListByNextToken(GetReportScheduleListByNextTokenRequest request) throws MarketplaceWebServiceException {
1506
        return invoke(GetReportScheduleListByNextTokenResponse.class, convertGetReportScheduleListByNextToken(request));
1507
    }
1508
 
1509
    /**
1510
     * Non-blocking Get Report Schedule List By Next Token 
1511
     * <p/>
1512
     * Returns <code>future</code> pointer to GetReportScheduleListByNextTokenResponse
1513
     * <p/>
1514
     * If response is ready, call to <code>future.get()</code> 
1515
     * will return GetReportScheduleListByNextTokenResponse. 
1516
     * <p/>
1517
     * If response is not ready, call to <code>future.get()</code> will block the 
1518
     * calling thread until response is returned. 
1519
     * <p/>
1520
     * Note, <code>future.get()</code> will throw wrapped runtime exception. 
1521
     * <p/>
1522
     * If service error has occured, MarketplaceWebServiceException can be extracted with
1523
     * <code>exception.getCause()</code>
1524
     * <p/>
1525
     * Usage example for parallel processing:
1526
     * <pre>
1527
     *
1528
     *  List&lt;Future&lt;GetReportScheduleListByNextTokenResponse&gt;&gt; responses = new ArrayList&lt;Future&lt;GetReportScheduleListByNextTokenResponse&gt;&gt;();
1529
     *  for (GetReportScheduleListByNextTokenRequest request : requests) {
1530
     *      responses.add(client.getReportScheduleListByNextTokenAsync(request));
1531
     *  }
1532
     *  for (Future&lt;GetReportScheduleListByNextTokenResponse&gt; future : responses) {
1533
     *      while (!future.isDone()) {
1534
     *          Thread.yield();
1535
     *      }
1536
     *      try {
1537
     *          GetReportScheduleListByNextTokenResponse response = future.get();
1538
     *      // use response
1539
     *      } catch (Exception e) {
1540
     *          if (e instanceof MarketplaceWebServiceException) {
1541
     *              MarketplaceWebServiceException exception = MarketplaceWebServiceException.class.cast(e);
1542
     *          // handle MarketplaceWebServiceException
1543
     *          } else {
1544
     *          // handle other exceptions
1545
     *          }
1546
     *      }
1547
     *  }
1548
     * </pre>
1549
     *
1550
     * @param request
1551
     *          GetReportScheduleListByNextTokenRequest request
1552
     * @return Future&lt;GetReportScheduleListByNextTokenResponse&gt; future pointer to GetReportScheduleListByNextTokenResponse
1553
     * 
1554
     */
1555
    public Future<GetReportScheduleListByNextTokenResponse> getReportScheduleListByNextTokenAsync(final GetReportScheduleListByNextTokenRequest request) {
1556
        Future<GetReportScheduleListByNextTokenResponse> response = asyncExecutor.submit(new Callable<GetReportScheduleListByNextTokenResponse>() {
1557
 
1558
            public GetReportScheduleListByNextTokenResponse call() throws MarketplaceWebServiceException {
1559
                return getReportScheduleListByNextToken(request);
1560
            }
1561
            });
1562
        return response;
1563
    }
1564
 
1565
    /**
1566
     * Get Report List By Next Token 
1567
     *
1568
     * retrieve the next batch of list items and if there are more items to retrieve
1569
     * 
1570
     * @param request
1571
     *          GetReportListByNextTokenRequest request
1572
     * @return
1573
     *          GetReportListByNextToken Response from the service
1574
     *
1575
     * @throws MarketplaceWebServiceException
1576
     */
1577
    public GetReportListByNextTokenResponse getReportListByNextToken(GetReportListByNextTokenRequest request) throws MarketplaceWebServiceException {
1578
        return invoke(GetReportListByNextTokenResponse.class, convertGetReportListByNextToken(request));
1579
    }
1580
 
1581
    /**
1582
     * Non-blocking Get Report List By Next Token 
1583
     * <p/>
1584
     * Returns <code>future</code> pointer to GetReportListByNextTokenResponse
1585
     * <p/>
1586
     * If response is ready, call to <code>future.get()</code> 
1587
     * will return GetReportListByNextTokenResponse. 
1588
     * <p/>
1589
     * If response is not ready, call to <code>future.get()</code> will block the 
1590
     * calling thread until response is returned. 
1591
     * <p/>
1592
     * Note, <code>future.get()</code> will throw wrapped runtime exception. 
1593
     * <p/>
1594
     * If service error has occured, MarketplaceWebServiceException can be extracted with
1595
     * <code>exception.getCause()</code>
1596
     * <p/>
1597
     * Usage example for parallel processing:
1598
     * <pre>
1599
     *
1600
     *  List&lt;Future&lt;GetReportListByNextTokenResponse&gt;&gt; responses = new ArrayList&lt;Future&lt;GetReportListByNextTokenResponse&gt;&gt;();
1601
     *  for (GetReportListByNextTokenRequest request : requests) {
1602
     *      responses.add(client.getReportListByNextTokenAsync(request));
1603
     *  }
1604
     *  for (Future&lt;GetReportListByNextTokenResponse&gt; future : responses) {
1605
     *      while (!future.isDone()) {
1606
     *          Thread.yield();
1607
     *      }
1608
     *      try {
1609
     *          GetReportListByNextTokenResponse response = future.get();
1610
     *      // use response
1611
     *      } catch (Exception e) {
1612
     *          if (e instanceof MarketplaceWebServiceException) {
1613
     *              MarketplaceWebServiceException exception = MarketplaceWebServiceException.class.cast(e);
1614
     *          // handle MarketplaceWebServiceException
1615
     *          } else {
1616
     *          // handle other exceptions
1617
     *          }
1618
     *      }
1619
     *  }
1620
     * </pre>
1621
     *
1622
     * @param request
1623
     *          GetReportListByNextTokenRequest request
1624
     * @return Future&lt;GetReportListByNextTokenResponse&gt; future pointer to GetReportListByNextTokenResponse
1625
     * 
1626
     */
1627
    public Future<GetReportListByNextTokenResponse> getReportListByNextTokenAsync(final GetReportListByNextTokenRequest request) {
1628
        Future<GetReportListByNextTokenResponse> response = asyncExecutor.submit(new Callable<GetReportListByNextTokenResponse>() {
1629
 
1630
            public GetReportListByNextTokenResponse call() throws MarketplaceWebServiceException {
1631
                return getReportListByNextToken(request);
1632
            }
1633
            });
1634
        return response;
1635
    }
1636
 
1637
    /**
1638
     * Manage Report Schedule 
1639
     *
1640
     * Creates, updates, or deletes a report schedule
1641
     * for a given report type, such as order reports in particular.
1642
     * 
1643
     * @param request
1644
     *          ManageReportScheduleRequest request
1645
     * @return
1646
     *          ManageReportSchedule Response from the service
1647
     *
1648
     * @throws MarketplaceWebServiceException
1649
     */
1650
    public ManageReportScheduleResponse manageReportSchedule(ManageReportScheduleRequest request) throws MarketplaceWebServiceException {
1651
        return invoke(ManageReportScheduleResponse.class, convertManageReportSchedule(request));
1652
    }
1653
 
1654
    /**
1655
     * Non-blocking Manage Report Schedule 
1656
     * <p/>
1657
     * Returns <code>future</code> pointer to ManageReportScheduleResponse
1658
     * <p/>
1659
     * If response is ready, call to <code>future.get()</code> 
1660
     * will return ManageReportScheduleResponse. 
1661
     * <p/>
1662
     * If response is not ready, call to <code>future.get()</code> will block the 
1663
     * calling thread until response is returned. 
1664
     * <p/>
1665
     * Note, <code>future.get()</code> will throw wrapped runtime exception. 
1666
     * <p/>
1667
     * If service error has occured, MarketplaceWebServiceException can be extracted with
1668
     * <code>exception.getCause()</code>
1669
     * <p/>
1670
     * Usage example for parallel processing:
1671
     * <pre>
1672
     *
1673
     *  List&lt;Future&lt;ManageReportScheduleResponse&gt;&gt; responses = new ArrayList&lt;Future&lt;ManageReportScheduleResponse&gt;&gt;();
1674
     *  for (ManageReportScheduleRequest request : requests) {
1675
     *      responses.add(client.manageReportScheduleAsync(request));
1676
     *  }
1677
     *  for (Future&lt;ManageReportScheduleResponse&gt; future : responses) {
1678
     *      while (!future.isDone()) {
1679
     *          Thread.yield();
1680
     *      }
1681
     *      try {
1682
     *          ManageReportScheduleResponse response = future.get();
1683
     *      // use response
1684
     *      } catch (Exception e) {
1685
     *          if (e instanceof MarketplaceWebServiceException) {
1686
     *              MarketplaceWebServiceException exception = MarketplaceWebServiceException.class.cast(e);
1687
     *          // handle MarketplaceWebServiceException
1688
     *          } else {
1689
     *          // handle other exceptions
1690
     *          }
1691
     *      }
1692
     *  }
1693
     * </pre>
1694
     *
1695
     * @param request
1696
     *          ManageReportScheduleRequest request
1697
     * @return Future&lt;ManageReportScheduleResponse&gt; future pointer to ManageReportScheduleResponse
1698
     * 
1699
     */
1700
    public Future<ManageReportScheduleResponse> manageReportScheduleAsync(final ManageReportScheduleRequest request) {
1701
        Future<ManageReportScheduleResponse> response = asyncExecutor.submit(new Callable<ManageReportScheduleResponse>() {
1702
 
1703
            public ManageReportScheduleResponse call() throws MarketplaceWebServiceException {
1704
                return manageReportSchedule(request);
1705
            }
1706
            });
1707
        return response;
1708
    }
1709
 
1710
    /**
1711
     * Get Report Request Count 
1712
     *
1713
     * returns a count of report requests; by default all the report
1714
     * requests in the last 90 days
1715
     * 
1716
     * @param request
1717
     *          GetReportRequestCountRequest request
1718
     * @return
1719
     *          GetReportRequestCount Response from the service
1720
     *
1721
     * @throws MarketplaceWebServiceException
1722
     */
1723
    public GetReportRequestCountResponse getReportRequestCount(GetReportRequestCountRequest request) throws MarketplaceWebServiceException {
1724
        return invoke(GetReportRequestCountResponse.class, convertGetReportRequestCount(request));
1725
    }
1726
 
1727
    /**
1728
     * Non-blocking Get Report Request Count 
1729
     * <p/>
1730
     * Returns <code>future</code> pointer to GetReportRequestCountResponse
1731
     * <p/>
1732
     * If response is ready, call to <code>future.get()</code> 
1733
     * will return GetReportRequestCountResponse. 
1734
     * <p/>
1735
     * If response is not ready, call to <code>future.get()</code> will block the 
1736
     * calling thread until response is returned. 
1737
     * <p/>
1738
     * Note, <code>future.get()</code> will throw wrapped runtime exception. 
1739
     * <p/>
1740
     * If service error has occured, MarketplaceWebServiceException can be extracted with
1741
     * <code>exception.getCause()</code>
1742
     * <p/>
1743
     * Usage example for parallel processing:
1744
     * <pre>
1745
     *
1746
     *  List&lt;Future&lt;GetReportRequestCountResponse&gt;&gt; responses = new ArrayList&lt;Future&lt;GetReportRequestCountResponse&gt;&gt;();
1747
     *  for (GetReportRequestCountRequest request : requests) {
1748
     *      responses.add(client.getReportRequestCountAsync(request));
1749
     *  }
1750
     *  for (Future&lt;GetReportRequestCountResponse&gt; future : responses) {
1751
     *      while (!future.isDone()) {
1752
     *          Thread.yield();
1753
     *      }
1754
     *      try {
1755
     *          GetReportRequestCountResponse response = future.get();
1756
     *      // use response
1757
     *      } catch (Exception e) {
1758
     *          if (e instanceof MarketplaceWebServiceException) {
1759
     *              MarketplaceWebServiceException exception = MarketplaceWebServiceException.class.cast(e);
1760
     *          // handle MarketplaceWebServiceException
1761
     *          } else {
1762
     *          // handle other exceptions
1763
     *          }
1764
     *      }
1765
     *  }
1766
     * </pre>
1767
     *
1768
     * @param request
1769
     *          GetReportRequestCountRequest request
1770
     * @return Future&lt;GetReportRequestCountResponse&gt; future pointer to GetReportRequestCountResponse
1771
     * 
1772
     */
1773
    public Future<GetReportRequestCountResponse> getReportRequestCountAsync(final GetReportRequestCountRequest request) {
1774
        Future<GetReportRequestCountResponse> response = asyncExecutor.submit(new Callable<GetReportRequestCountResponse>() {
1775
 
1776
            public GetReportRequestCountResponse call() throws MarketplaceWebServiceException {
1777
                return getReportRequestCount(request);
1778
            }
1779
            });
1780
        return response;
1781
    }
1782
 
1783
    /**
1784
     * Get Report Schedule List 
1785
     *
1786
     * returns the list of report schedules
1787
     * 
1788
     * @param request
1789
     *          GetReportScheduleListRequest request
1790
     * @return
1791
     *          GetReportScheduleList Response from the service
1792
     *
1793
     * @throws MarketplaceWebServiceException
1794
     */
1795
    public GetReportScheduleListResponse getReportScheduleList(GetReportScheduleListRequest request) throws MarketplaceWebServiceException {
1796
        return invoke(GetReportScheduleListResponse.class, convertGetReportScheduleList(request));
1797
    }
1798
 
1799
    /**
1800
     * Non-blocking Get Report Schedule List 
1801
     * <p/>
1802
     * Returns <code>future</code> pointer to GetReportScheduleListResponse
1803
     * <p/>
1804
     * If response is ready, call to <code>future.get()</code> 
1805
     * will return GetReportScheduleListResponse. 
1806
     * <p/>
1807
     * If response is not ready, call to <code>future.get()</code> will block the 
1808
     * calling thread until response is returned. 
1809
     * <p/>
1810
     * Note, <code>future.get()</code> will throw wrapped runtime exception. 
1811
     * <p/>
1812
     * If service error has occured, MarketplaceWebServiceException can be extracted with
1813
     * <code>exception.getCause()</code>
1814
     * <p/>
1815
     * Usage example for parallel processing:
1816
     * <pre>
1817
     *
1818
     *  List&lt;Future&lt;GetReportScheduleListResponse&gt;&gt; responses = new ArrayList&lt;Future&lt;GetReportScheduleListResponse&gt;&gt;();
1819
     *  for (GetReportScheduleListRequest request : requests) {
1820
     *      responses.add(client.getReportScheduleListAsync(request));
1821
     *  }
1822
     *  for (Future&lt;GetReportScheduleListResponse&gt; future : responses) {
1823
     *      while (!future.isDone()) {
1824
     *          Thread.yield();
1825
     *      }
1826
     *      try {
1827
     *          GetReportScheduleListResponse response = future.get();
1828
     *      // use response
1829
     *      } catch (Exception e) {
1830
     *          if (e instanceof MarketplaceWebServiceException) {
1831
     *              MarketplaceWebServiceException exception = MarketplaceWebServiceException.class.cast(e);
1832
     *          // handle MarketplaceWebServiceException
1833
     *          } else {
1834
     *          // handle other exceptions
1835
     *          }
1836
     *      }
1837
     *  }
1838
     * </pre>
1839
     *
1840
     * @param request
1841
     *          GetReportScheduleListRequest request
1842
     * @return Future&lt;GetReportScheduleListResponse&gt; future pointer to GetReportScheduleListResponse
1843
     * 
1844
     */
1845
    public Future<GetReportScheduleListResponse> getReportScheduleListAsync(final GetReportScheduleListRequest request) {
1846
        Future<GetReportScheduleListResponse> response = asyncExecutor.submit(new Callable<GetReportScheduleListResponse>() {
1847
 
1848
            public GetReportScheduleListResponse call() throws MarketplaceWebServiceException {
1849
                return getReportScheduleList(request);
1850
            }
1851
            });
1852
        return response;
1853
    }
1854
 
1855
	/**
1856
	 * Remove all leading whitespace, trailing whitespace, repeated whitespace
1857
	 * and replace any interior whitespace with a single space
1858
	 */
1859
    private static String clean(String s) {
1860
    	return s
1861
    		.replaceAll("\\s", " ")
1862
    		.replaceAll(" {2,}", " ")
1863
    		.trim();
1864
    }
1865
 
1866
    public static String quoteAppName(String s) {
1867
        return clean(s)
1868
            .replace("\\", "\\\\")
1869
            .replace("/", "\\/");
1870
    }
1871
 
1872
    public static String quoteAppVersion(String s) {
1873
        return clean(s)
1874
            .replace("\\", "\\\\")
1875
            .replace("(", "\\(");
1876
    }
1877
 
1878
    public static String quoteAttributeName(String s) {
1879
        return clean(s)
1880
            .replace("\\", "\\\\")
1881
            .replace("=", "\\=");
1882
    }
1883
 
1884
    public static String quoteAttributeValue(String s) {
1885
        return clean(s)
1886
            .replace("\\", "\\\\")
1887
            .replace(";", "\\;")
1888
            .replace(")", "\\)");
1889
    }
1890
 
1891
    private static final String mwsClientLibraryVersion = "2013-06-10";
1892
 
1893
 
1894
    // Private API ------------------------------------------------------------//
1895
 
1896
    /**
1897
     * Configure HttpClient with set of defaults as well as configuration
1898
     * from MarketplaceWebServiceConfig instance
1899
     *
1900
     */
1901
    private HttpClient configureHttpClient(
1902
    		String applicationName,
1903
    		String applicationVersion) {
1904
 
1905
        // respect a user-provided User-Agent header as-is, but if none is provided
1906
        // then generate one satisfying the MWS User-Agent requirements
1907
        if(config.getUserAgent()==null) {
1908
        	config.setUserAgent(
1909
        			quoteAppName(applicationName), 
1910
        			quoteAppVersion(applicationVersion), 
1911
        			quoteAttributeValue("Java/"+System.getProperty("java.version")+
1912
        			"/"+System.getProperty("java.class.version")+
1913
        			"/"+System.getProperty("java.vendor")), 
1914
 
1915
        			quoteAttributeName("Platform"), 
1916
        			quoteAttributeValue(""+System.getProperty("os.name")+
1917
        			"/"+System.getProperty("os.arch")+
1918
        			"/"+System.getProperty("os.version")),
1919
 
1920
        			quoteAttributeName("MWSClientVersion"), 
1921
        			quoteAttributeValue(mwsClientLibraryVersion));
1922
        }
1923
 
1924
        defaultHeaders.add(new BasicHeader("X-Amazon-User-Agent", config.getUserAgent()));
1925
 
1926
 
1927
        /* Set http client parameters */
1928
    	BasicHttpParams httpParams = new BasicHttpParams();
1929
 
1930
        httpParams.setParameter(CoreProtocolPNames.USER_AGENT, config.getUserAgent());
1931
 
1932
 
1933
        /* Set connection parameters */
1934
        HttpConnectionParams.setConnectionTimeout(httpParams, config.getConnectionTimeout());
1935
        HttpConnectionParams.setSoTimeout(httpParams, config.getSoTimeout());
1936
        HttpConnectionParams.setStaleCheckingEnabled(httpParams, true);
1937
        HttpConnectionParams.setTcpNoDelay(httpParams, true);    
1938
 
1939
 
1940
        /* Set connection manager */
1941
        PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager();
1942
        connectionManager.setMaxTotal(config.getMaxAsyncQueueSize());
1943
        connectionManager.setDefaultMaxPerRoute(config.getMaxAsyncQueueSize());
1944
 
1945
        /* Set http client */
1946
        httpClient = new DefaultHttpClient(connectionManager, httpParams);
1947
        httpContext = new BasicHttpContext();
1948
 
1949
 
1950
        /* Set proxy if configured */
1951
        if (config.isSetProxyHost() && config.isSetProxyPort()) {
1952
            log.info("Configuring Proxy. Proxy Host: " + config.getProxyHost() +
1953
                    "Proxy Port: " + config.getProxyPort() );
1954
            final HttpHost hostConfiguration = new HttpHost(config.getProxyHost(), config.getProxyPort(), (usesHttps(config.getServiceURL()) ? "https" : "http") );
1955
            httpContext = new BasicHttpContext();
1956
            httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, hostConfiguration); 
1957
 
1958
            if (config.isSetProxyUsername() && config.isSetProxyPassword()) {
1959
                credentialsProvider.setCredentials (new AuthScope(
1960
                                          config.getProxyHost(),
1961
                                          config.getProxyPort()),
1962
                                          new UsernamePasswordCredentials(
1963
                                              config.getProxyUsername(),
1964
                                              config.getProxyPassword()));
1965
                httpContext.setAttribute(ClientContext.CREDS_PROVIDER, credentialsProvider);
1966
 
1967
            }
1968
 
1969
        }
1970
 
1971
        return httpClient;
1972
    }
1973
 
1974
    /**
1975
     * Stream the response into an output stream.
1976
     */
1977
    private void copyResponseToOutputStream(InputStream from, OutputStream to) throws IOException {
1978
    	byte[] buffer = new byte[1048576]; // 1024*1024
1979
    	int read = 0;
1980
    	while ((read = from.read(buffer)) > 0) {
1981
    		to.write(buffer, 0, read);
1982
    	}
1983
    }
1984
 
1985
    private void addRequiredParameters(Map< String, String > parameters) throws SignatureException {
1986
      parameters.put("Version", config.getServiceVersion());
1987
      parameters.put("SignatureVersion", "2");
1988
      parameters.put("Timestamp", getFormattedTimestamp());
1989
      parameters.put("AWSAccessKeyId",  this.awsAccessKeyId);
1990
      parameters.put("Signature", signParameters(parameters, this.awsSecretAccessKey));
1991
    }
1992
 
1993
    private String getSubmitFeedUrlParameters( Map< String, String > parameters ) throws SignatureException, MarketplaceWebServiceException {
1994
        addRequiredParameters(parameters);
1995
 
1996
        StringBuilder sb = new StringBuilder();
1997
        for( Entry< String, String > entry : parameters.entrySet() ) {
1998
            if( sb.length() != 0 ) {
1999
                sb.append( "&" );
2000
            }
2001
 
2002
            try {
2003
                String key = URLEncoder.encode( entry.getKey(), "UTF-8" );
2004
                String value = URLEncoder.encode( entry.getValue(), "UTF-8" );
2005
 
2006
                sb.append( key + "=" + value );
2007
            }
2008
            catch( Throwable t ) {
2009
                log.error("Caught Exception", t);
2010
                throw new MarketplaceWebServiceException(t);
2011
            }
2012
        }
2013
 
2014
        return sb.toString();
2015
    }
2016
 
2017
    private <T> T invoke(Class<T> clazz, Map<String, String> parameters)
2018
    throws MarketplaceWebServiceException {
2019
        return invoke( clazz, parameters, null );
2020
    }
2021
 
2022
    @SuppressWarnings("serial")
2023
    private <T, U> T invoke(Class<T> clazz, Map<String, String> parameters, U request ) throws MarketplaceWebServiceException {
2024
 
2025
        String actionName = parameters.get("Action");
2026
        T response = null;
2027
        String responseBodyString = null;
2028
        ResponseHeaderMetadata responseHeaderMetadata = null;
2029
        Method responseHeaderMetadataSetter = null;
2030
 
2031
        HttpPost method = null;
2032
 
2033
        try {
2034
 
2035
            responseHeaderMetadataSetter = clazz.getMethod("setResponseHeaderMetadata", ResponseHeaderMetadata.class);
2036
 
2037
            if(!config.isSetServiceURL()){
2038
                throw new MarketplaceWebServiceException("Missing serviceUrl configuration value. You may obtain a list of valid MWS URLs by consulting the MWS Developer's Guide, or reviewing the sample code published along side this library.", -1, "InvalidServiceUrl", "Sender", null,  null, null) {
2039
                };
2040
            }
2041
            // SubmitFeed will be the only MWS API function that will stream requests to the server.
2042
            if( request instanceof SubmitFeedRequest ) {
2043
 
2044
                // For SubmitFeed, HTTP body is reserved for the Feed Content and the function parameters 
2045
                // are contained within the HTTP header
2046
                SubmitFeedRequest sfr = (SubmitFeedRequest)request;
2047
 
2048
                method = new HttpPost( config.getServiceURL() + "?" + getSubmitFeedUrlParameters( parameters ) );
2049
 
2050
                method.setEntity( new InputStreamEntity(sfr.getFeedContent() , -1) );
2051
 
2052
                String contentMD5 = sfr.getContentMD5();
2053
 
2054
                if(contentMD5!=null) {
2055
                	method.addHeader(new BasicHeader("Content-MD5", contentMD5));
2056
                }               
2057
 
2058
                /* Set content type and encoding - encoding and charset are ignored right now because
2059
                 * octet-stream is the only supported transport of MWS feeds. */
2060
                method.addHeader(new BasicHeader("Content-Type", sfr.getContentType().toString()));
2061
 
2062
            }
2063
            else {
2064
                method = new HttpPost(config.getServiceURL());
2065
                log.debug("Adding required parameters...");
2066
                addRequiredParametersToRequest(method, parameters);               
2067
 
2068
                /* Set content type and encoding */
2069
                log.debug("Setting content-type to application/x-www-form-urlencoded; charset=" + DEFAULT_ENCODING.toLowerCase());
2070
                method.addHeader(new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=" + DEFAULT_ENCODING.toLowerCase()));
2071
 
2072
                log.debug("Done adding additional required parameters. Parameters now: " + parameters);
2073
            }
2074
 
2075
            for(Header head: defaultHeaders) {
2076
            	method.addHeader(head);
2077
            }
2078
 
2079
        } 
2080
        catch( Throwable t ) {
2081
            throw new MarketplaceWebServiceException( t );
2082
        }
2083
 
2084
        int status = -1;
2085
 
2086
        log.debug("Invoking" + actionName + " request. Current parameters: " + parameters);
2087
        try {
2088
            boolean shouldRetry = true;
2089
            int retries = 0;
2090
            do {
2091
                log.debug("Sending Request to host:  " + config.getServiceURL());
2092
 
2093
                try {
2094
 
2095
                    /* Submit request */
2096
                    HttpResponse postResponse;
2097
                    postResponse = httpClient.execute(method, httpContext);
2098
                    status = postResponse.getStatusLine().getStatusCode();
2099
 
2100
                    responseHeaderMetadata = getResponseHeaderMetadata(postResponse);
2101
 
2102
                    // GetFeedSubmissionResult and GetReport will be the only MWS API functions that will stream
2103
                    // server responses.
2104
                    boolean isStreamingResponse = (request instanceof GetFeedSubmissionResultRequest || request instanceof GetReportRequest); 
2105
 
2106
                    if( !isStreamingResponse ) {
2107
                        // SubmitFeed
2108
                        responseBodyString = getResponsBodyAsString(postResponse.getEntity().getContent());
2109
                        assert( responseBodyString != null );
2110
                    }
2111
 
2112
                    /* Successful response. Attempting to unmarshal into the <Action>Response type */
2113
                    if (status == HttpStatus.SC_OK && responseBodyString != null) {
2114
                        shouldRetry = false;
2115
                        log.debug("Received Response. Status: " + status + ". " +
2116
                                "Response Body: " + responseBodyString);
2117
 
2118
                        log.debug("Attempting to unmarshal into the " + actionName + "Response type...");
2119
                        response = clazz.cast(getUnmarshaller().unmarshal(new StreamSource(new StringReader(responseBodyString))));
2120
                        responseHeaderMetadataSetter.invoke(response, responseHeaderMetadata);
2121
 
2122
                        log.debug("Unmarshalled response into " + actionName + "Response type.");
2123
 
2124
                    } 
2125
                    else if (status == HttpStatus.SC_OK && isStreamingResponse ) {
2126
 
2127
                        Method outputStreamGetter = null;
2128
                        for( Method m : request.getClass().getMethods() ) {
2129
                            if( m.getName().matches( "get.+OutputStream$" ) ) {
2130
                                outputStreamGetter = m;
2131
                            }
2132
                        }
2133
 
2134
                        OutputStream originalOs = (OutputStream)outputStreamGetter.invoke( request, new Object[0] );
2135
 
2136
                        MessageDigest messageDigest = MessageDigest.getInstance("MD5");
2137
                        DigestOutputStream os = new DigestOutputStream(originalOs, messageDigest);
2138
 
2139
                        // Streaming-response-as-unnamed-body responses from MWS
2140
                        // must carry the generated unique request id as a HTTP
2141
                        // header (x-amz-request-id) as it cannot be passed in a
2142
                        // wrapper to the XML response.
2143
                        String requestIdFromHeader = null;
2144
                        {
2145
                            requestIdFromHeader = getFirstHeader(postResponse, "x-amz-request-id").getValue();
2146
 
2147
                            // Avoid use of the JDK-1.6-only isEmpty() call.
2148
                            if(requestIdFromHeader==null || requestIdFromHeader.length()==0) {
2149
                                throw new MarketplaceWebServiceException(
2150
                                    "no request id returned in the x-amz-request-id HTTP header " +
2151
                                    "for a streaming response call - please contact Amazon");
2152
                            }
2153
                        }
2154
 
2155
                        String returnedContentMD5 = null;
2156
 
2157
                       	returnedContentMD5 = getFirstHeader(postResponse, "Content-MD5").getValue();
2158
 
2159
                        copyResponseToOutputStream(postResponse.getEntity().getContent(), os);
2160
 
2161
                        // Streaming-response-as-unnamed-body responses from MWS
2162
                        // must also carry a Content-MD5 header and it must
2163
                        // match the calculated MD5 for the body.
2164
                        String calculatedContentMD5 = new String(Base64.encodeBase64(messageDigest.digest()), "UTF-8");
2165
                        if(!calculatedContentMD5.equals(returnedContentMD5)) {
2166
                            throw new MarketplaceWebServiceException(
2167
                                    "Content-MD5 HTTP header transmitted by MWS ("+returnedContentMD5+") " +
2168
                                    "does not match the calculated MD5 ("+calculatedContentMD5+") " +
2169
                                    "in request id "+requestIdFromHeader+" - please contact Amazon");
2170
                        }
2171
 
2172
                        response = clazz.newInstance();
2173
                        responseHeaderMetadataSetter.invoke(response, responseHeaderMetadata);
2174
                        if( clazz == GetFeedSubmissionResultResponse.class ) {
2175
                            GetFeedSubmissionResultResponse r = (GetFeedSubmissionResultResponse)response;
2176
                            r.setGetFeedSubmissionResultResult( new GetFeedSubmissionResultResult( returnedContentMD5 ) );
2177
                            r.setResponseMetadata( new ResponseMetadata( requestIdFromHeader ) );
2178
                        }
2179
                        else if( clazz == GetReportResponse.class ) {
2180
                            GetReportResponse r = (GetReportResponse)response;
2181
                            r.setGetReportResult( new GetReportResult( returnedContentMD5 ) );
2182
                            r.setResponseMetadata( new ResponseMetadata( requestIdFromHeader ) );
2183
                        } else {
2184
                            throw new MarketplaceWebServiceException(
2185
                                    "unexpected streaming-response class "+clazz.getName()
2186
                                    +" - please contact Amazon");
2187
                        }
2188
 
2189
                        shouldRetry = false;
2190
                        log.debug( "Received streaming response." );
2191
 
2192
                    } else { /* Unsucessful response. Attempting to unmarshall into ErrorResponse  type */
2193
 
2194
                        if( isStreamingResponse ) {
2195
                            // Response body contains error message.
2196
                            responseBodyString = getResponsBodyAsString(postResponse.getEntity().getContent());
2197
                        }
2198
 
2199
 
2200
                        log.debug("Received Response. Status: " + status + "." );
2201
 
2202
                        if (status == HttpStatus.SC_INTERNAL_SERVER_ERROR
2203
                        		&& !(request instanceof SubmitFeedRequest)
2204
                        		&& pauseIfRetryNeeded(++retries)){
2205
                            shouldRetry = true;
2206
                        }else {
2207
                            log.debug("Attempting to unmarshal into the ErrorResponse type...");
2208
                            ErrorResponse errorResponse = (ErrorResponse) getUnmarshaller().unmarshal(new StreamSource(new StringReader(responseBodyString)));
2209
 
2210
                            log.debug("Unmarshalled response into the ErrorResponse type.");
2211
 
2212
                            com.amazonaws.mws.model.Error error = errorResponse.getError().get(0);
2213
 
2214
                            if(status == HttpStatus.SC_SERVICE_UNAVAILABLE  
2215
                            		&& !(error.getCode().equals("RequestThrottled"))
2216
                            		&& !(request instanceof SubmitFeedRequest)
2217
                            		&& pauseIfRetryNeeded(++retries)) {
2218
                        		shouldRetry = true;
2219
                            } else {
2220
                            	shouldRetry=false;	
2221
                            	throw new MarketplaceWebServiceException(
2222
                            		(((request instanceof SubmitFeedRequest) && (error.getType().equals("Receiver")))? 
2223
                            			error.getMessage() + " [Cannot retry SubmitFeed request: must reset InputStream to retry.]" : 
2224
                            			error.getMessage()),
2225
                                    status,
2226
                                    error.getCode(),
2227
                                    error.getType(),
2228
                                    errorResponse.getRequestId(),
2229
                                    errorResponse.toXML(),
2230
                                    responseHeaderMetadata);
2231
                            }
2232
                        }
2233
                    }
2234
                } catch (JAXBException je) {
2235
                    /* Response cannot be unmarshalled neither as <Action>Response or ErrorResponse types.
2236
                    Checking for other possible errors. */
2237
 
2238
                    log.debug ("Caught JAXBException", je);
2239
                    log.debug("Response cannot be unmarshalled neither as " + actionName + "Response or ErrorResponse types." +
2240
                            "Checking for other possible errors.");
2241
 
2242
                    MarketplaceWebServiceException awse = processErrors(responseBodyString, status, responseHeaderMetadata);
2243
 
2244
                    throw awse;
2245
 
2246
                } catch (IOException ioe) {
2247
                    log.error("Caught IOException exception", ioe);
2248
                    throw new MarketplaceWebServiceException("Internal Error", ioe);
2249
                } catch (Exception e) {
2250
                    log.error("Caught Exception", e);
2251
                    throw new MarketplaceWebServiceException(e);
2252
                } finally {
2253
                    method.releaseConnection();
2254
                }
2255
            } while (shouldRetry);
2256
 
2257
        } catch (MarketplaceWebServiceException se) {
2258
            log.error("Caught MarketplaceWebServiceException", se);
2259
            throw se;
2260
 
2261
        } catch (Throwable t) {
2262
            log.error("Caught Exception", t);
2263
            throw new MarketplaceWebServiceException(t);
2264
        }
2265
        return response;
2266
    }
2267
 
2268
    private Header getFirstHeader(HttpResponse response, String headerName)
2269
    {
2270
        Header[] responseHeaders = response.getHeaders(headerName);
2271
        if (responseHeaders.length > 0)
2272
        {
2273
            return responseHeaders[0];
2274
        }
2275
    	return null;
2276
    }
2277
    private ResponseHeaderMetadata getResponseHeaderMetadata(HttpResponse response) {
2278
      Header requestId = null;
2279
      Header responseContext = null;
2280
      Header timestamp = null;
2281
 
2282
      requestId = getFirstHeader(response, "x-mws-request-id");
2283
      responseContext = getFirstHeader(response, "x-mws-response-context");
2284
      timestamp = getFirstHeader(response, "x-mws-timestamp");
2285
 
2286
      return new ResponseHeaderMetadata(
2287
        requestId != null ? requestId.getValue() : null,
2288
        responseContext != null ? responseContext.getValue() : null,
2289
        timestamp != null ? timestamp.getValue() : null);
2290
    }
2291
 
2292
    /**
2293
     * Calculate content MD5 header values for feeds stored on disk.
2294
     */
2295
    private String computeContentMD5HeaderValue( FileInputStream fis ) 
2296
        throws IOException, NoSuchAlgorithmException {
2297
 
2298
        DigestInputStream dis = new DigestInputStream( fis, MessageDigest.getInstance( "MD5" ));
2299
 
2300
        byte[] buffer = new byte[8192];
2301
        while( dis.read( buffer ) > 0 );
2302
 
2303
        String md5Content = new String( org.apache.commons.codec.binary.Base64.encodeBase64(dis.getMessageDigest().digest()) );           
2304
 
2305
        // Effectively resets the stream to be beginning of the file via a FileChannel.
2306
        fis.getChannel().position( 0 );
2307
 
2308
        return md5Content;
2309
    }
2310
 
2311
    /**
2312
     * Read stream into string
2313
     * @param input stream to read
2314
     */
2315
    private String getResponsBodyAsString(InputStream input) throws IOException {
2316
        String responsBodyString = null;
2317
        try {
2318
            Reader reader = new InputStreamReader(input, DEFAULT_ENCODING);
2319
            StringBuilder b = new StringBuilder();
2320
            char[] c = new char[1024];
2321
            int len;
2322
            while (0 < (len = reader.read(c))) {
2323
                b.append(c, 0, len);
2324
            }
2325
            responsBodyString = b.toString();
2326
        } finally {
2327
            input.close();
2328
        }
2329
        return responsBodyString;
2330
    }
2331
 
2332
    /**
2333
     * Exponential sleep on failed request. Sleeps and returns true if retry needed
2334
     * @param retries current retry
2335
     * @throws java.lang.InterruptedException
2336
     */
2337
    private boolean pauseIfRetryNeeded(int retries)
2338
          throws InterruptedException {
2339
        if (retries <= config.getMaxErrorRetry()) {
2340
            long delay = (long) (Math.pow(4, retries) * 100L);
2341
            log.debug("Retriable error detected, will retry in " + delay + "ms, attempt numer: " + retries);
2342
            Thread.sleep(delay);
2343
            return true;
2344
        } else {
2345
            return false;
2346
        }
2347
    }
2348
 
2349
    /**
2350
     * Add authentication related and version parameter and set request body
2351
     * with all of the parameters
2352
     * @throws UnsupportedEncodingException 
2353
     */
2354
    private void addRequiredParametersToRequest(HttpPost method, Map<String, String> parameters)
2355
            throws SignatureException, UnsupportedEncodingException {
2356
        addRequiredParameters(parameters);
2357
        List <NameValuePair> parameterList = new ArrayList <NameValuePair>();
2358
        for (Entry<String, String> entry : parameters.entrySet()) {
2359
            String key = entry.getKey()==null ? "" : entry.getKey();
2360
            String value = entry.getValue()==null ? "" : entry.getValue();
2361
            parameterList.add(new BasicNameValuePair(key, value));
2362
        }
2363
        method.setEntity(new UrlEncodedFormEntity(parameterList, HTTP.UTF_8));
2364
 
2365
    }
2366
 
2367
    private MarketplaceWebServiceException processErrors(String responseString, int status, ResponseHeaderMetadata metadata)  {
2368
        MarketplaceWebServiceException ex = null;
2369
        Matcher matcher = null;
2370
        if (responseString != null && responseString.startsWith("<")) {
2371
            matcher = ERROR_PATTERN_ONE.matcher(responseString);
2372
            if (matcher.matches()) {
2373
                ex = new MarketplaceWebServiceException(matcher.group(3), status,
2374
                        matcher.group(2), "Unknown", matcher.group(1), responseString, metadata);
2375
            } else {
2376
                matcher = ERROR_PATTERN_TWO.matcher(responseString);
2377
                if (matcher.matches()) {
2378
                    ex = new MarketplaceWebServiceException(matcher.group(2), status,
2379
                            matcher.group(1), "Unknown", matcher.group(4), responseString, metadata);
2380
            } else {
2381
                ex =  new MarketplaceWebServiceException("Internal Error", status, metadata);
2382
                log.error("Service Error. Response Status: " + status + ". Received message: " + responseString);
2383
            }
2384
            }
2385
        } else {
2386
            ex =  new MarketplaceWebServiceException("Internal Error", status, metadata);
2387
            log.error("Service Error. Response Status: " + status + ". Received message: " + responseString);
2388
        }
2389
        return ex;
2390
    }
2391
 
2392
    /**
2393
     * Formats date as ISO 8601 timestamp
2394
     */
2395
    private String getFormattedTimestamp() {
2396
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
2397
        df.setTimeZone(TimeZone.getTimeZone("UTC"));
2398
        return df.format(new Date());
2399
    }
2400
 
2401
    /**
2402
     * Computes RFC 2104-compliant HMAC signature for request parameters
2403
     * Implements AWS Signature, as per following spec:
2404
     *
2405
     * If Signature Version is 1, it performs the following:
2406
     *
2407
     * Sorts all  parameters (including SignatureVersion and excluding Signature,
2408
     * the value of which is being created), ignoring case.
2409
     *
2410
     * Iterate over the sorted list and append the parameter name (in original case)
2411
     * and then its value. It will not URL-encode the parameter values before
2412
     * constructing this string. There are no separators.
2413
     *
2414
     * If Signature Version is 2, string to sign is based on following:
2415
     *
2416
     *    1. The HTTP Request Method followed by an ASCII newline (%0A)
2417
     *    2. The HTTP Host header in the form of lowercase host, followed by an ASCII newline.
2418
     *    3. The URL encoded HTTP absolute path component of the URI
2419
     *       (up to but not including the query string parameters);
2420
     *       if this is empty use a forward '/'. This parameter is followed by an ASCII newline.
2421
     *    4. The concatenation of all query string components (names and values)
2422
     *       as UTF-8 characters which are URL encoded as per RFC 3986
2423
     *       (hex characters MUST be uppercase), sorted using lexicographic byte ordering.
2424
     *       Parameter names are separated from their values by the '=' character
2425
     *       (ASCII character 61), even if the value is empty.
2426
     *       Pairs of parameter and values are separated by the '&' character (ASCII code 38).
2427
     *
2428
     */
2429
    private String signParameters(Map<String, String> parameters, String key)
2430
            throws  SignatureException {
2431
 
2432
        String signatureVersion = parameters.get("SignatureVersion");
2433
        String algorithm = "HmacSHA1";
2434
        String stringToSign = null;
2435
        if ("2".equals(signatureVersion)) {
2436
            algorithm = config.getSignatureMethod();
2437
            parameters.put("SignatureMethod", algorithm);
2438
            stringToSign = calculateStringToSignV2(parameters);
2439
        } else {
2440
            throw new SignatureException("Invalid Signature Version specified");
2441
        }
2442
        log.debug("Calculated string to sign: " + stringToSign);
2443
        return sign(stringToSign, key, algorithm);
2444
    }
2445
 
2446
    /**
2447
     * Calculate String to Sign for SignatureVersion 2
2448
     * @param parameters request parameters
2449
     * @return String to Sign
2450
     * @throws java.security.SignatureException
2451
     */
2452
    private String calculateStringToSignV2(Map<String, String> parameters)
2453
            throws SignatureException {
2454
        StringBuilder data = new StringBuilder();
2455
        data.append("POST");
2456
        data.append("\n");
2457
        URI endpoint = null;
2458
        try {
2459
            endpoint = new URI(config.getServiceURL().toLowerCase());
2460
        } catch (URISyntaxException ex) {
2461
            log.error("URI Syntax Exception", ex);
2462
            throw new SignatureException("URI Syntax Exception thrown " +
2463
                    "while constructing string to sign", ex);
2464
        }
2465
        data.append(endpoint.getHost());
2466
        if (!usesAStandardPort(config.getServiceURL())) {
2467
            data.append(":");
2468
            data.append(endpoint.getPort());
2469
        }
2470
        data.append("\n");
2471
        String uri = endpoint.getPath();
2472
        if (uri == null || uri.length() == 0) {
2473
            uri = "/";
2474
        }
2475
        data.append(uri);
2476
        data.append("\n");
2477
        Map<String, String> sorted = new TreeMap<String, String>();
2478
        sorted.putAll(parameters);
2479
        Iterator<Map.Entry<String, String>> pairs = sorted.entrySet().iterator();
2480
        while (pairs.hasNext()) {
2481
            Map.Entry<String, String> pair = pairs.next();
2482
            String key = pair.getKey();
2483
            data.append(urlEncode(key));
2484
            data.append("=");
2485
            String value = pair.getValue();
2486
            data.append(urlEncode(value));
2487
            if (pairs.hasNext()) {
2488
                data.append("&");
2489
            }
2490
        }
2491
        System.out.println(data.toString());
2492
        return data.toString();
2493
    }
2494
 
2495
    private static boolean usesHttps(String url){
2496
        URL urlToCheck;
2497
        try {
2498
            urlToCheck = new URL(url);
2499
        } catch (MalformedURLException e) {
2500
            return false;
2501
        }
2502
        if (urlToCheck.getProtocol().equals("https")){
2503
            return true;
2504
        }else
2505
        {
2506
            return false;
2507
        }
2508
    }
2509
 
2510
    private static int extractPortNumber(String url, boolean usesHttps) {
2511
        URL urlToCheck;
2512
        try {
2513
            urlToCheck = new URL(url);
2514
        } catch (MalformedURLException e) {
2515
            throw new RuntimeException("not a URL", e);
2516
        }
2517
 
2518
        int portNumber = urlToCheck.getPort();
2519
        if (portNumber == -1){
2520
            // no port was specified
2521
            if (usesHttps){
2522
                // it uses https, so we should return the standard https port number
2523
                return 443;
2524
            }else
2525
            {
2526
                // it uses http, so we should return the standard http port number
2527
                return 80;
2528
            }
2529
        }else
2530
        {
2531
            return portNumber;
2532
        }
2533
    }
2534
 
2535
    private static boolean usesAStandardPort(String url) {
2536
        boolean usesHttps = usesHttps(url);
2537
        int portNumber = extractPortNumber(url, usesHttps);
2538
        return usesHttps && portNumber == 443
2539
            || !usesHttps && portNumber == 80;
2540
    }
2541
 
2542
    private String urlEncode(String rawValue) {
2543
        String value = rawValue==null ? "" : rawValue;
2544
        String encoded = null;
2545
        try {
2546
            encoded = URLEncoder.encode(value, DEFAULT_ENCODING)
2547
                                        .replace("+", "%20")
2548
                                        .replace("*", "%2A")
2549
                                        .replace("%7E","~");
2550
        } catch (UnsupportedEncodingException ex) {
2551
            log.error("Unsupported Encoding Exception", ex);
2552
            throw new RuntimeException(ex);
2553
        }
2554
        return encoded;
2555
    }
2556
 
2557
    /**
2558
     * Computes RFC 2104-compliant HMAC signature.
2559
     *
2560
     */
2561
    private String sign(String data, String key, String algorithm) throws SignatureException {
2562
        byte [] signature;
2563
        try {
2564
            Mac mac = Mac.getInstance(algorithm);
2565
            mac.init(new SecretKeySpec(key.getBytes(), algorithm));
2566
            signature = Base64.encodeBase64(mac.doFinal(data.getBytes(DEFAULT_ENCODING)));
2567
        } catch (Exception e) {
2568
            throw new SignatureException("Failed to generate signature: " + e.getMessage(), e);
2569
        }
2570
 
2571
        return new String(signature);
2572
    }
2573
 
2574
    /**
2575
     * Get unmarshaller for current thread
2576
     */
2577
    private Unmarshaller getUnmarshaller() {
2578
        return unmarshaller.get();
2579
    }
2580
                                    /**
2581
     * Convert GetReportRequest to name value pairs
2582
     */
2583
    private Map<String, String> convertGetReport(GetReportRequest request) {
2584
 
2585
        Map<String, String> params = new HashMap<String, String>();
2586
        params.put("Action", "GetReport");
2587
        if (request.isSetMarketplace()) {
2588
            params.put("Marketplace", request.getMarketplace());
2589
        }
2590
        if (request.isSetMerchant()) {
2591
            params.put("Merchant", request.getMerchant());
2592
        }
2593
        if (request.isSetReportId()) {
2594
            params.put("ReportId", request.getReportId());
2595
        }
2596
 
2597
        return params;
2598
    }
2599
 
2600
                                    /**
2601
     * Convert GetReportScheduleCountRequest to name value pairs
2602
     */
2603
    private Map<String, String> convertGetReportScheduleCount(GetReportScheduleCountRequest request) {
2604
 
2605
        Map<String, String> params = new HashMap<String, String>();
2606
        params.put("Action", "GetReportScheduleCount");
2607
        if (request.isSetMarketplace()) {
2608
            params.put("Marketplace", request.getMarketplace());
2609
        }
2610
        if (request.isSetMerchant()) {
2611
            params.put("Merchant", request.getMerchant());
2612
        }
2613
        if (request.isSetReportTypeList()) {
2614
            TypeList  reportTypeList = request.getReportTypeList();
2615
            java.util.List<String> typeList  =  reportTypeList.getType();
2616
            for  (String type : typeList) { 
2617
                params.put("ReportTypeList" + "." + "Type" + "."  + (typeList.indexOf(type) + 1), type);
2618
            }   
2619
        } 
2620
 
2621
        return params;
2622
    }
2623
 
2624
                                    /**
2625
     * Convert GetReportRequestListByNextTokenRequest to name value pairs
2626
     */
2627
    private Map<String, String> convertGetReportRequestListByNextToken(GetReportRequestListByNextTokenRequest request) {
2628
 
2629
        Map<String, String> params = new HashMap<String, String>();
2630
        params.put("Action", "GetReportRequestListByNextToken");
2631
        if (request.isSetMarketplace()) {
2632
            params.put("Marketplace", request.getMarketplace());
2633
        }
2634
        if (request.isSetMerchant()) {
2635
            params.put("Merchant", request.getMerchant());
2636
        }
2637
        if (request.isSetNextToken()) {
2638
            params.put("NextToken", request.getNextToken());
2639
        }
2640
 
2641
        return params;
2642
    }
2643
 
2644
                                    /**
2645
     * Convert UpdateReportAcknowledgementsRequest to name value pairs
2646
     */
2647
    private Map<String, String> convertUpdateReportAcknowledgements(UpdateReportAcknowledgementsRequest request) {
2648
 
2649
        Map<String, String> params = new HashMap<String, String>();
2650
        params.put("Action", "UpdateReportAcknowledgements");
2651
        if (request.isSetMarketplace()) {
2652
            params.put("Marketplace", request.getMarketplace());
2653
        }
2654
        if (request.isSetMerchant()) {
2655
            params.put("Merchant", request.getMerchant());
2656
        }
2657
        if (request.isSetReportIdList()) {
2658
            IdList  reportIdList = request.getReportIdList();
2659
            java.util.List<String> idList  =  reportIdList.getId();
2660
            for  (String id : idList) { 
2661
                params.put("ReportIdList" + "." + "Id" + "."  + (idList.indexOf(id) + 1), id);
2662
            }   
2663
        } 
2664
        if (request.isSetAcknowledged()) {
2665
            params.put("Acknowledged", request.isAcknowledged() + "");
2666
        }
2667
 
2668
        return params;
2669
    }
2670
 
2671
                                    /**
2672
     * Convert SubmitFeedRequest to name value pairs
2673
     */
2674
    private Map<String, String> convertSubmitFeed(SubmitFeedRequest request) {
2675
 
2676
        Map<String, String> params = new HashMap<String, String>();
2677
        params.put("Action", "SubmitFeed");
2678
        if (request.isSetMarketplace()) {
2679
            params.put("Marketplace", request.getMarketplace());
2680
        }
2681
        if (request.isSetMarketplaceIdList()) {
2682
            IdList marketplaceIdList = request.getMarketplaceIdList();
2683
            List<String> idList = marketplaceIdList.getId();
2684
 
2685
            for (int i = 0; i < idList.size(); i++) {
2686
                params.put("MarketplaceIdList.Id." + (i + 1), idList.get(i));
2687
            }
2688
        }
2689
        if (request.isSetMerchant()) {
2690
            params.put("Merchant", request.getMerchant());
2691
        }
2692
        if (request.isSetFeedType()) {
2693
            params.put("FeedType", request.getFeedType());
2694
        }
2695
        if (request.isSetPurgeAndReplace()) {
2696
            params.put("PurgeAndReplace", request.isPurgeAndReplace() + "");
2697
        }
2698
 
2699
        return params;
2700
    }
2701
 
2702
                                    /**
2703
     * Convert GetReportCountRequest to name value pairs
2704
     */
2705
    private Map<String, String> convertGetReportCount(GetReportCountRequest request) {
2706
 
2707
        Map<String, String> params = new HashMap<String, String>();
2708
        params.put("Action", "GetReportCount");
2709
        if (request.isSetMarketplace()) {
2710
            params.put("Marketplace", request.getMarketplace());
2711
        }
2712
        if (request.isSetMerchant()) {
2713
            params.put("Merchant", request.getMerchant());
2714
        }
2715
        if (request.isSetReportTypeList()) {
2716
            TypeList  reportTypeList = request.getReportTypeList();
2717
            java.util.List<String> typeList  =  reportTypeList.getType();
2718
            for  (String type : typeList) { 
2719
                params.put("ReportTypeList" + "." + "Type" + "."  + (typeList.indexOf(type) + 1), type);
2720
            }   
2721
        } 
2722
        if (request.isSetAcknowledged()) {
2723
            params.put("Acknowledged", request.isAcknowledged() + "");
2724
        }
2725
        if (request.isSetAvailableFromDate()) {
2726
            params.put("AvailableFromDate", request.getAvailableFromDate() + "");
2727
        }
2728
        if (request.isSetAvailableToDate()) {
2729
            params.put("AvailableToDate", request.getAvailableToDate() + "");
2730
        }
2731
 
2732
        return params;
2733
    }
2734
 
2735
                                    /**
2736
     * Convert GetFeedSubmissionListByNextTokenRequest to name value pairs
2737
     */
2738
    private Map<String, String> convertGetFeedSubmissionListByNextToken(GetFeedSubmissionListByNextTokenRequest request) {
2739
 
2740
        Map<String, String> params = new HashMap<String, String>();
2741
        params.put("Action", "GetFeedSubmissionListByNextToken");
2742
        if (request.isSetMarketplace()) {
2743
            params.put("Marketplace", request.getMarketplace());
2744
        }
2745
        if (request.isSetMerchant()) {
2746
            params.put("Merchant", request.getMerchant());
2747
        }
2748
        if (request.isSetNextToken()) {
2749
            params.put("NextToken", request.getNextToken());
2750
        }
2751
 
2752
        return params;
2753
    }
2754
 
2755
                                    /**
2756
     * Convert CancelFeedSubmissionsRequest to name value pairs
2757
     */
2758
    private Map<String, String> convertCancelFeedSubmissions(CancelFeedSubmissionsRequest request) {
2759
 
2760
        Map<String, String> params = new HashMap<String, String>();
2761
        params.put("Action", "CancelFeedSubmissions");
2762
        if (request.isSetMarketplace()) {
2763
            params.put("Marketplace", request.getMarketplace());
2764
        }
2765
        if (request.isSetMerchant()) {
2766
            params.put("Merchant", request.getMerchant());
2767
        }
2768
        if (request.isSetFeedSubmissionIdList()) {
2769
            IdList  feedSubmissionIdList = request.getFeedSubmissionIdList();
2770
            java.util.List<String> idList  =  feedSubmissionIdList.getId();
2771
            for  (String id : idList) { 
2772
                params.put("FeedSubmissionIdList" + "." + "Id" + "."  + (idList.indexOf(id) + 1), id);
2773
            }   
2774
        } 
2775
        if (request.isSetFeedTypeList()) {
2776
            TypeList  feedTypeList = request.getFeedTypeList();
2777
            java.util.List<String> typeList  =  feedTypeList.getType();
2778
            for  (String type : typeList) { 
2779
                params.put("FeedTypeList" + "." + "Type" + "."  + (typeList.indexOf(type) + 1), type);
2780
            }   
2781
        } 
2782
        if (request.isSetSubmittedFromDate()) {
2783
            params.put("SubmittedFromDate", request.getSubmittedFromDate() + "");
2784
        }
2785
        if (request.isSetSubmittedToDate()) {
2786
            params.put("SubmittedToDate", request.getSubmittedToDate() + "");
2787
        }
2788
 
2789
        return params;
2790
    }
2791
 
2792
                                    /**
2793
     * Convert RequestReportRequest to name value pairs
2794
     */
2795
    private Map<String, String> convertRequestReport(RequestReportRequest request) {
2796
 
2797
        Map<String, String> params = new HashMap<String, String>();
2798
        params.put("Action", "RequestReport");
2799
        if (request.isSetMarketplaceIdList()) {
2800
            IdList marketplaceIdList = request.getMarketplaceIdList();
2801
            List<String> idList = marketplaceIdList.getId();
2802
 
2803
            for (int i = 0; i < idList.size(); i++) {
2804
                params.put("MarketplaceIdList.Id." + (i + 1), idList.get(i));
2805
            }
2806
        }
2807
        if (request.isSetMarketplace()) {
2808
            params.put("Marketplace", request.getMarketplace());
2809
        }
2810
        if (request.isSetMerchant()) {
2811
            params.put("Merchant", request.getMerchant());
2812
        }
2813
        if (request.isSetReportType()) {
2814
            params.put("ReportType", request.getReportType());
2815
        }
2816
        if (request.isSetStartDate()) {
2817
            params.put("StartDate", request.getStartDate() + "");
2818
        }
2819
        if (request.isSetEndDate()) {
2820
            params.put("EndDate", request.getEndDate() + "");
2821
        }
2822
        if (request.isSetReportOptions()) {
2823
            params.put("ReportOptions", request.getReportOptions());
2824
        }
2825
 
2826
        return params;
2827
    }
2828
 
2829
                                    /**
2830
     * Convert GetFeedSubmissionCountRequest to name value pairs
2831
     */
2832
    private Map<String, String> convertGetFeedSubmissionCount(GetFeedSubmissionCountRequest request) {
2833
 
2834
        Map<String, String> params = new HashMap<String, String>();
2835
        params.put("Action", "GetFeedSubmissionCount");
2836
        if (request.isSetMarketplace()) {
2837
            params.put("Marketplace", request.getMarketplace());
2838
        }
2839
        if (request.isSetMerchant()) {
2840
            params.put("Merchant", request.getMerchant());
2841
        }
2842
        if (request.isSetFeedTypeList()) {
2843
            TypeList  feedTypeList = request.getFeedTypeList();
2844
            java.util.List<String> typeList  =  feedTypeList.getType();
2845
            for  (String type : typeList) { 
2846
                params.put("FeedTypeList" + "." + "Type" + "."  + (typeList.indexOf(type) + 1), type);
2847
            }   
2848
        } 
2849
        if (request.isSetFeedProcessingStatusList()) {
2850
            StatusList  feedProcessingStatusList = request.getFeedProcessingStatusList();
2851
            java.util.List<String> statusList  =  feedProcessingStatusList.getStatus();
2852
            for  (String status : statusList) { 
2853
                params.put("FeedProcessingStatusList" + "." + "Status" + "."  + (statusList.indexOf(status) + 1), status);
2854
            }   
2855
        } 
2856
        if (request.isSetSubmittedFromDate()) {
2857
            params.put("SubmittedFromDate", request.getSubmittedFromDate() + "");
2858
        }
2859
        if (request.isSetSubmittedToDate()) {
2860
            params.put("SubmittedToDate", request.getSubmittedToDate() + "");
2861
        }
2862
 
2863
        return params;
2864
    }
2865
 
2866
                                    /**
2867
     * Convert CancelReportRequestsRequest to name value pairs
2868
     */
2869
    private Map<String, String> convertCancelReportRequests(CancelReportRequestsRequest request) {
2870
 
2871
        Map<String, String> params = new HashMap<String, String>();
2872
        params.put("Action", "CancelReportRequests");
2873
        if (request.isSetMarketplace()) {
2874
            params.put("Marketplace", request.getMarketplace());
2875
        }
2876
        if (request.isSetMerchant()) {
2877
            params.put("Merchant", request.getMerchant());
2878
        }
2879
        if (request.isSetReportRequestIdList()) {
2880
            IdList  reportRequestIdList = request.getReportRequestIdList();
2881
            java.util.List<String> idList  =  reportRequestIdList.getId();
2882
            for  (String id : idList) { 
2883
                params.put("ReportRequestIdList" + "." + "Id" + "."  + (idList.indexOf(id) + 1), id);
2884
            }   
2885
        } 
2886
        if (request.isSetReportTypeList()) {
2887
            TypeList  reportTypeList = request.getReportTypeList();
2888
            java.util.List<String> typeList  =  reportTypeList.getType();
2889
            for  (String type : typeList) { 
2890
                params.put("ReportTypeList" + "." + "Type" + "."  + (typeList.indexOf(type) + 1), type);
2891
            }   
2892
        } 
2893
        if (request.isSetReportProcessingStatusList()) {
2894
            StatusList  reportProcessingStatusList = request.getReportProcessingStatusList();
2895
            java.util.List<String> statusList  =  reportProcessingStatusList.getStatus();
2896
            for  (String status : statusList) { 
2897
                params.put("ReportProcessingStatusList" + "." + "Status" + "."  + (statusList.indexOf(status) + 1), status);
2898
            }   
2899
        } 
2900
        if (request.isSetRequestedFromDate()) {
2901
            params.put("RequestedFromDate", request.getRequestedFromDate() + "");
2902
        }
2903
        if (request.isSetRequestedToDate()) {
2904
            params.put("RequestedToDate", request.getRequestedToDate() + "");
2905
        }
2906
 
2907
        return params;
2908
    }
2909
 
2910
                                    /**
2911
     * Convert GetReportListRequest to name value pairs
2912
     */
2913
    private Map<String, String> convertGetReportList(GetReportListRequest request) {
2914
 
2915
        Map<String, String> params = new HashMap<String, String>();
2916
        params.put("Action", "GetReportList");
2917
 
2918
        if (request.isSetMarketplace()) {
2919
            params.put("Marketplace", request.getMarketplace());
2920
        }
2921
        if (request.isSetMerchant()) {
2922
            params.put("Merchant", request.getMerchant());
2923
        }
2924
        if (request.isSetMaxCount()) {
2925
            params.put("MaxCount", request.getMaxCount() + "");
2926
        }
2927
        if (request.isSetReportTypeList()) {
2928
            TypeList  reportTypeList = request.getReportTypeList();
2929
            java.util.List<String> typeList  =  reportTypeList.getType();
2930
            for  (String type : typeList) { 
2931
                params.put("ReportTypeList" + "." + "Type" + "."  + (typeList.indexOf(type) + 1), type);
2932
            }   
2933
        } 
2934
        if (request.isSetAcknowledged()) {
2935
            params.put("Acknowledged", request.isAcknowledged() + "");
2936
        }
2937
        if (request.isSetAvailableFromDate()) {
2938
            params.put("AvailableFromDate", request.getAvailableFromDate() + "");
2939
        }
2940
        if (request.isSetAvailableToDate()) {
2941
            params.put("AvailableToDate", request.getAvailableToDate() + "");
2942
        }
2943
        if (request.isSetReportRequestIdList()) {
2944
            IdList  reportRequestIdList = request.getReportRequestIdList();
2945
            java.util.List<String> idList  =  reportRequestIdList.getId();
2946
            for  (String id : idList) { 
2947
                params.put("ReportRequestIdList" + "." + "Id" + "."  + (idList.indexOf(id) + 1), id);
2948
            }   
2949
        } 
2950
 
2951
        return params;
2952
    }
2953
 
2954
                                    /**
2955
     * Convert GetFeedSubmissionResultRequest to name value pairs
2956
     */
2957
    private Map<String, String> convertGetFeedSubmissionResult(GetFeedSubmissionResultRequest request) {
2958
 
2959
        Map<String, String> params = new HashMap<String, String>();
2960
        params.put("Action", "GetFeedSubmissionResult");
2961
        if (request.isSetMarketplace()) {
2962
            params.put("Marketplace", request.getMarketplace());
2963
        }
2964
        if (request.isSetMerchant()) {
2965
            params.put("Merchant", request.getMerchant());
2966
        }
2967
        if (request.isSetFeedSubmissionId()) {
2968
            params.put("FeedSubmissionId", request.getFeedSubmissionId());
2969
        }
2970
 
2971
        return params;
2972
    }
2973
 
2974
                                    /**
2975
     * Convert GetFeedSubmissionListRequest to name value pairs
2976
     */
2977
    private Map<String, String> convertGetFeedSubmissionList(GetFeedSubmissionListRequest request) {
2978
 
2979
        Map<String, String> params = new HashMap<String, String>();
2980
        params.put("Action", "GetFeedSubmissionList");
2981
        if (request.isSetMarketplace()) {
2982
            params.put("Marketplace", request.getMarketplace());
2983
        }
2984
        if (request.isSetMerchant()) {
2985
            params.put("Merchant", request.getMerchant());
2986
        }
2987
        if (request.isSetFeedSubmissionIdList()) {
2988
            IdList  feedSubmissionIdList = request.getFeedSubmissionIdList();
2989
            java.util.List<String> idList  =  feedSubmissionIdList.getId();
2990
            for  (String id : idList) { 
2991
                params.put("FeedSubmissionIdList" + "." + "Id" + "."  + (idList.indexOf(id) + 1), id);
2992
            }   
2993
        } 
2994
        if (request.isSetMaxCount()) {
2995
            params.put("MaxCount", request.getMaxCount() + "");
2996
        }
2997
        if (request.isSetFeedTypeList()) {
2998
            TypeList  feedTypeList = request.getFeedTypeList();
2999
            java.util.List<String> typeList  =  feedTypeList.getType();
3000
            for  (String type : typeList) { 
3001
                params.put("FeedTypeList" + "." + "Type" + "."  + (typeList.indexOf(type) + 1), type);
3002
            }   
3003
        } 
3004
        if (request.isSetFeedProcessingStatusList()) {
3005
            StatusList  feedProcessingStatusList = request.getFeedProcessingStatusList();
3006
            java.util.List<String> statusList  =  feedProcessingStatusList.getStatus();
3007
            for  (String status : statusList) { 
3008
                params.put("FeedProcessingStatusList" + "." + "Status" + "."  + (statusList.indexOf(status) + 1), status);
3009
            }   
3010
        } 
3011
        if (request.isSetSubmittedFromDate()) {
3012
            params.put("SubmittedFromDate", request.getSubmittedFromDate() + "");
3013
        }
3014
        if (request.isSetSubmittedToDate()) {
3015
            params.put("SubmittedToDate", request.getSubmittedToDate() + "");
3016
        }
3017
 
3018
        return params;
3019
    }
3020
 
3021
                                    /**
3022
     * Convert GetReportRequestListRequest to name value pairs
3023
     */
3024
    private Map<String, String> convertGetReportRequestList(GetReportRequestListRequest request) {
3025
 
3026
        Map<String, String> params = new HashMap<String, String>();
3027
        params.put("Action", "GetReportRequestList");
3028
        if (request.isSetMarketplace()) {
3029
            params.put("Marketplace", request.getMarketplace());
3030
        }
3031
        if (request.isSetMerchant()) {
3032
            params.put("Merchant", request.getMerchant());
3033
        }
3034
        if (request.isSetReportRequestIdList()) {
3035
            IdList  reportRequestIdList = request.getReportRequestIdList();
3036
            java.util.List<String> idList  =  reportRequestIdList.getId();
3037
            for  (String id : idList) { 
3038
                params.put("ReportRequestIdList" + "." + "Id" + "."  + (idList.indexOf(id) + 1), id);
3039
            }   
3040
        } 
3041
        if (request.isSetReportTypeList()) {
3042
            TypeList  reportTypeList = request.getReportTypeList();
3043
            java.util.List<String> typeList  =  reportTypeList.getType();
3044
            for  (String type : typeList) { 
3045
                params.put("ReportTypeList" + "." + "Type" + "."  + (typeList.indexOf(type) + 1), type);
3046
            }   
3047
        } 
3048
        if (request.isSetReportProcessingStatusList()) {
3049
            StatusList  reportProcessingStatusList = request.getReportProcessingStatusList();
3050
            java.util.List<String> statusList  =  reportProcessingStatusList.getStatus();
3051
            for  (String status : statusList) { 
3052
                params.put("ReportProcessingStatusList" + "." + "Status" + "."  + (statusList.indexOf(status) + 1), status);
3053
            }   
3054
        } 
3055
        if (request.isSetMaxCount()) {
3056
            params.put("MaxCount", request.getMaxCount() + "");
3057
        }
3058
        if (request.isSetRequestedFromDate()) {
3059
            params.put("RequestedFromDate", request.getRequestedFromDate() + "");
3060
        }
3061
        if (request.isSetRequestedToDate()) {
3062
            params.put("RequestedToDate", request.getRequestedToDate() + "");
3063
        }
3064
 
3065
        return params;
3066
    }
3067
 
3068
                                    /**
3069
     * Convert GetReportScheduleListByNextTokenRequest to name value pairs
3070
     */
3071
    private Map<String, String> convertGetReportScheduleListByNextToken(GetReportScheduleListByNextTokenRequest request) {
3072
 
3073
        Map<String, String> params = new HashMap<String, String>();
3074
        params.put("Action", "GetReportScheduleListByNextToken");
3075
        if (request.isSetMarketplace()) {
3076
            params.put("Marketplace", request.getMarketplace());
3077
        }
3078
        if (request.isSetMerchant()) {
3079
            params.put("Merchant", request.getMerchant());
3080
        }
3081
        if (request.isSetNextToken()) {
3082
            params.put("NextToken", request.getNextToken());
3083
        }
3084
 
3085
        return params;
3086
    }
3087
 
3088
                                    /**
3089
     * Convert GetReportListByNextTokenRequest to name value pairs
3090
     */
3091
    private Map<String, String> convertGetReportListByNextToken(GetReportListByNextTokenRequest request) {
3092
 
3093
        Map<String, String> params = new HashMap<String, String>();
3094
        params.put("Action", "GetReportListByNextToken");
3095
        if (request.isSetMarketplace()) {
3096
            params.put("Marketplace", request.getMarketplace());
3097
        }
3098
        if (request.isSetMerchant()) {
3099
            params.put("Merchant", request.getMerchant());
3100
        }
3101
        if (request.isSetNextToken()) {
3102
            params.put("NextToken", request.getNextToken());
3103
        }
3104
 
3105
        return params;
3106
    }
3107
 
3108
                                    /**
3109
     * Convert ManageReportScheduleRequest to name value pairs
3110
     */
3111
    private Map<String, String> convertManageReportSchedule(ManageReportScheduleRequest request) {
3112
 
3113
        Map<String, String> params = new HashMap<String, String>();
3114
        params.put("Action", "ManageReportSchedule");
3115
        if (request.isSetMarketplace()) {
3116
            params.put("Marketplace", request.getMarketplace());
3117
        }
3118
        if (request.isSetMerchant()) {
3119
            params.put("Merchant", request.getMerchant());
3120
        }
3121
        if (request.isSetReportType()) {
3122
            params.put("ReportType", request.getReportType());
3123
        }
3124
        if (request.isSetSchedule()) {
3125
            params.put("Schedule", request.getSchedule());
3126
        }
3127
        if (request.isSetScheduledDate()) {
3128
            params.put("ScheduledDate", request.getScheduledDate() + "");
3129
        }
3130
 
3131
        return params;
3132
    }
3133
 
3134
                                    /**
3135
     * Convert GetReportRequestCountRequest to name value pairs
3136
     */
3137
    private Map<String, String> convertGetReportRequestCount(GetReportRequestCountRequest request) {
3138
 
3139
        Map<String, String> params = new HashMap<String, String>();
3140
        params.put("Action", "GetReportRequestCount");
3141
        if (request.isSetMarketplace()) {
3142
            params.put("Marketplace", request.getMarketplace());
3143
        }
3144
        if (request.isSetMerchant()) {
3145
            params.put("Merchant", request.getMerchant());
3146
        }
3147
        if (request.isSetReportTypeList()) {
3148
            TypeList  reportTypeList = request.getReportTypeList();
3149
            java.util.List<String> typeList  =  reportTypeList.getType();
3150
            for  (String type : typeList) { 
3151
                params.put("ReportTypeList" + "." + "Type" + "."  + (typeList.indexOf(type) + 1), type);
3152
            }   
3153
        } 
3154
        if (request.isSetReportProcessingStatusList()) {
3155
            StatusList  reportProcessingStatusList = request.getReportProcessingStatusList();
3156
            java.util.List<String> statusList  =  reportProcessingStatusList.getStatus();
3157
            for  (String status : statusList) { 
3158
                params.put("ReportProcessingStatusList" + "." + "Status" + "."  + (statusList.indexOf(status) + 1), status);
3159
            }   
3160
        } 
3161
        if (request.isSetRequestedFromDate()) {
3162
            params.put("RequestedFromDate", request.getRequestedFromDate() + "");
3163
        }
3164
        if (request.isSetRequestedToDate()) {
3165
            params.put("RequestedToDate", request.getRequestedToDate() + "");
3166
        }
3167
 
3168
        return params;
3169
    }
3170
 
3171
                                    /**
3172
     * Convert GetReportScheduleListRequest to name value pairs
3173
     */
3174
    private Map<String, String> convertGetReportScheduleList(GetReportScheduleListRequest request) {
3175
 
3176
        Map<String, String> params = new HashMap<String, String>();
3177
        params.put("Action", "GetReportScheduleList");
3178
        if (request.isSetMarketplace()) {
3179
            params.put("Marketplace", request.getMarketplace());
3180
        }
3181
        if (request.isSetMerchant()) {
3182
            params.put("Merchant", request.getMerchant());
3183
        }
3184
        if (request.isSetReportTypeList()) {
3185
            TypeList  reportTypeList = request.getReportTypeList();
3186
            java.util.List<String> typeList  =  reportTypeList.getType();
3187
            for  (String type : typeList) { 
3188
                params.put("ReportTypeList" + "." + "Type" + "."  + (typeList.indexOf(type) + 1), type);
3189
            }   
3190
        } 
3191
 
3192
        return params;
3193
    }
3194
 
3195
 
3196
}