// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.api.ads.adwords.lib.utils;
import com.google.api.ads.adwords.lib.client.AdWordsSession;
import com.google.api.ads.adwords.lib.utils.DetailedReportDownloadResponseException.Builder;
import com.google.api.ads.common.lib.exception.AuthenticationException;
import com.google.api.ads.common.lib.utils.Streams;
import com.google.api.ads.common.lib.utils.XmlFieldExtractor;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpResponse;
import com.google.common.base.Preconditions;
import com.google.inject.Inject;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.nio.charset.Charset;
import java.util.Map;
/**
* Actual implementation of download functionality.
*/
class AdHocReportDownloadHelperImpl implements AdHocReportDownloadHelperInterface {
private final AdWordsSession session;
private final ReportRequestFactoryHelper reportRequestFactoryHelper;
private final ReportBodyProviderFactory reportBodyProviderFactory;
private final XmlFieldExtractor xmlFieldExtractor;
/** Constructor used by Guice. */
@Inject
AdHocReportDownloadHelperImpl(AdWordsSession session,
ReportRequestFactoryHelper reportRequestFactoryHelper,
ReportBodyProviderFactory reportBodyProviderFactory,
XmlFieldExtractor xmlFieldExtractor) {
this.session = session;
this.reportRequestFactoryHelper = reportRequestFactoryHelper;
this.reportBodyProviderFactory = reportBodyProviderFactory;
this.xmlFieldExtractor = xmlFieldExtractor;
}
@Override
public ReportDownloadResponse downloadReport(
ReportRequest reportRequest, Builder exceptionBuilder)
throws ReportDownloadResponseException, ReportException {
return handleResponse(downloadReport(reportRequest), exceptionBuilder);
}
@Override
public RawReportDownloadResponse downloadReport(ReportRequest reportRequest)
throws ReportException {
try {
String apiVersion = reportRequest.getApiVersion();
String downloadUrl = generateReportUrl(apiVersion);
HttpRequestFactory requestFactory =
reportRequestFactoryHelper.getHttpRequestFactory(downloadUrl, apiVersion);
ReportBodyProvider reportBodyProvider =
reportBodyProviderFactory.getReportBodyProvider(reportRequest);
HttpRequest httpRequest = requestFactory
.buildPostRequest(new GenericUrl(downloadUrl), reportBodyProvider.getHttpContent());
HttpResponse response = httpRequest.execute();
Charset charSet = REPORT_CHARSET;
// Unfortunately, HttpResponse.getContentCharset defaults to Charsets.ISO_8859_1 if the
// underlying MediaType is null or doesn't have a Charset parameter. Since we want to
// default to REPORT_CHARSET, we have to inspect the MediaType ourselves.
if (response.getMediaType() != null
&& response.getMediaType().getCharsetParameter() != null) {
charSet = response.getMediaType().getCharsetParameter();
}
return new RawReportDownloadResponse(response.getStatusCode(), response.getContent(), charSet,
reportRequest.getDownloadFormat().name());
} catch (MalformedURLException e) {
throw new ReportException("Created invalid report download URL.", e);
} catch (IOException e) {
throw new ReportException("Problem sending data to report download server.", e);
} catch (AuthenticationException e) {
throw new ReportException("Problem with OAuth authorization.", e);
}
}
@Override
public ReportDownloadResponse handleResponse(
RawReportDownloadResponse rawResponse, Builder exceptionBuilder)
throws ReportDownloadResponseException {
Preconditions.checkNotNull(rawResponse, "Null response");
Preconditions.checkNotNull(exceptionBuilder, "Null exception builder");
if (rawResponse.getHttpStatus() == HttpURLConnection.HTTP_OK) {
return new ReportDownloadResponse(rawResponse);
}
String responseText;
if (rawResponse.getInputStream() == null) {
responseText = "";
} else {
try {
responseText = Streams.readAll(rawResponse.getInputStream(), rawResponse.getCharset());
} catch (IOException e1) {
throw new ReportDownloadResponseException(rawResponse.getHttpStatus(), e1);
}
}
DetailedReportDownloadResponseException exception =
exceptionBuilder.build(rawResponse.getHttpStatus(), responseText);
Map<String, String> fields =
xmlFieldExtractor.extract(
new ByteArrayInputStream(responseText.getBytes(rawResponse.getCharset())),
new String[] {"fieldPath", "trigger", "type"});
exception.setFieldPath(fields.get("fieldPath"));
exception.setTrigger(fields.get("trigger"));
exception.setType(fields.get("type"));
throw exception;
}
/**
* Creates the report download URL.
*
* @param version to download from.
* @return url to download a report from.
*/
private String generateReportUrl(String version) {
return session.getEndpoint() + ReportRequestFactoryHelper.DOWNLOAD_SERVER_URI + '/' + version;
}
@Override
public int getReportDownloadTimeout() {
return reportRequestFactoryHelper.getReportDownloadTimeout();
}
@Override
public void setReportDownloadTimeout(int reportDownloadTimeout) {
reportRequestFactoryHelper.setReportDownloadTimeout(reportDownloadTimeout);
}
}