public MeasurementData measure(String requestSignature,
		IHttpTimingDownloader measurementDownloader,
		IHttpDownloader reportDownloader) {
		MeasurementData result = new MeasurementData();
		List<ReportData> reports = result.getReportData();
		for (int i = 0; i < probes.size(); i++) {
			ReportData reportData = probes.get(i).measure(
				requestorZoneId,
				requestorCustomerId,
				ownerZoneId,
				ownerCustomerId,
				providerId,
				this.cacheBusting,
				requestSignature,
				measurementDownloader,
				logger);
			
			if (null == reportData) {
				break;
			}
			
			reports.add(reportData);
			
			// Only continue if we successfully downloaded the probe
			if (!reportData.isSuccessful()) {
				break;
			}
		}
		
		ReportData currentReport;
		DownloadData downloadData;
		IReportURLFormatter urlFormatter = new ReportURLFormatter();
		for (int i = 0; i < reports.size(); i++) {
			int responseCode = 1;
			long measurement = 0;
			currentReport = reports.get(i);
			downloadData = currentReport.getDownloadData();
			if (downloadData.hasResponseCode() && !downloadData.getIsTimeout()) {
				switch (downloadData.getResponseCode()) {
				case HttpURLConnection.HTTP_OK:
					responseCode = 0;
					measurement = currentReport.getMeasurement();
					break;
				case HttpURLConnection.HTTP_NOT_FOUND:
					responseCode = 4;
					break;
				}
				
				reportDownloader.downloadFromURL(
					urlFormatter.urlFromDownloadData(
						requestSignature,
						ownerZoneId,
						ownerCustomerId,
						providerId,
						currentReport.getProbeId(),
						responseCode,
						measurement),
					urlFormatter.headersFromDownloadData(downloadData));
			}
			else {
				reportDownloader.downloadFromURL(
					urlFormatter.urlFromDownloadData(
						requestSignature,
						ownerZoneId,
						ownerCustomerId,
						providerId,
						currentReport.getProbeId(),
						responseCode,
						measurement));
			}
		}
		
		return result;
	}