<commit_before>/**
 * Copyright (c) 2011, 2015 Eurotech and/or its affiliates
 *
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   Eurotech
 */

package org.eclipse.kura.core.deployment.download;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.net.URLConnection;
import java.security.GeneralSecurityException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import javax.net.ssl.HttpsURLConnection;

import org.apache.commons.io.output.CountingOutputStream;
import org.eclipse.kura.KuraConnectException;
import org.eclipse.kura.KuraErrorCode;
import org.eclipse.kura.KuraException;
import org.eclipse.kura.core.deployment.CloudDeploymentHandlerV2.DOWNLOAD_STATUS;
import org.eclipse.kura.core.deployment.progress.ProgressEvent;
import org.eclipse.kura.core.deployment.progress.ProgressListener;
import org.eclipse.kura.ssl.SslManagerService;

public class DownloadCountingOutputStream extends CountingOutputStream {

	private static int PROP_RESOLUTION = 1024 * 4;
	private static int PROP_BUFFER_SIZE = 1024 * 4;
	private static int PROP_CONNECT_TIMEOUT = 5000;
	private static int PROP_READ_TIMEOUT = 6000;
	private static int PROP_BLOCK_DELAY = 1000;

	private final DeploymentPackageDownloadOptions options;
	// https://s3.amazonaws.com/kura-resources/dps/heater.dp

	private long totalBytes;

	private final SslManagerService m_sslManagerService;

	private final ProgressListener pl;

	InputStream is = null;

	private long m_currentStep = 1;
	
	private ExecutorService executor;
	private Future<Void> future;
	private long previous;
	private DOWNLOAD_STATUS m_downloadStatus = DOWNLOAD_STATUS.FAILED;
	

	public DownloadCountingOutputStream(OutputStream out, DeploymentPackageDownloadOptions options, ProgressListener callback,
			SslManagerService m_sslManagerService) {
		super(out);
		this.options = options;
		this.m_sslManagerService = m_sslManagerService;
		this.pl = callback;
		PROP_BUFFER_SIZE = options.getBlockSize();
		PROP_RESOLUTION = options.getNotifyBlockSize();
		PROP_BLOCK_DELAY = options.getBlockDelay();
		PROP_CONNECT_TIMEOUT = options.getTimeout();
	}

	public void setResolution(int resolution) {
		PROP_RESOLUTION = resolution;
	}

	public void setBufferSize(int size) {
		PROP_BUFFER_SIZE = size;
	}

	public void setConnectTimeout(int timeout) {
		PROP_CONNECT_TIMEOUT = timeout;
	}

	public void setReadTimeout(int timeout) {
		PROP_READ_TIMEOUT = timeout;
	}

	public void cancelDownload() throws Exception{
		if(executor != null){
			if(future != null){
				future.cancel(true);
				executor.shutdownNow();
				
				postProgressEvent(options.getClientId(), getByteCount(), totalBytes, DOWNLOAD_STATUS.FAILED, "Download cancelled");
			}
		}
	}
	
	public void startWork() throws KuraException {
		
		executor = Executors.newSingleThreadExecutor();
		
		future = executor.submit(new Callable<Void>(){

			@Override
			public Void call() throws Exception {
				URL localUrl = null;
				boolean shouldAuthenticate = false;
				try {
					shouldAuthenticate = (options.getUsername() != null) && (options.getPassword() != null)
							&& !(options.getUsername().trim().isEmpty() && !(options.getPassword().trim().isEmpty()));

					if (shouldAuthenticate) {
						Authenticator.setDefault(new Authenticator() {
							protected PasswordAuthentication getPasswordAuthentication() {
								return new PasswordAuthentication(options.getUsername(), options.getPassword().toCharArray());
							}
						});
					}

					localUrl = new URL(options.getDeployUrl());
					URLConnection urlConnection = localUrl.openConnection();
					urlConnection.setConnectTimeout(PROP_CONNECT_TIMEOUT);
					urlConnection.setReadTimeout(PROP_READ_TIMEOUT);

					try {
						if (urlConnection instanceof HttpsURLConnection) {
							((HttpsURLConnection) urlConnection).setSSLSocketFactory(m_sslManagerService.getSSLSocketFactory());
						} else if (!(urlConnection instanceof HttpURLConnection)) {
							postProgressEvent(options.getClientId(), getByteCount(), totalBytes, DOWNLOAD_STATUS.FAILED, "The request URL is not supported");
							throw new KuraConnectException("Unsupported protocol!");
						}
					} catch (GeneralSecurityException e) {
						postProgressEvent(options.getClientId(), getByteCount(), totalBytes, DOWNLOAD_STATUS.FAILED, e.getMessage());
						throw new KuraConnectException(e, "Unsupported protocol!");
					}

					is = localUrl.openStream();

					String s = urlConnection.getHeaderField("Content-Length");

					totalBytes = s != null ? Integer.parseInt(s) : -1;
					postProgressEvent(options.getClientId(), 0, totalBytes, DOWNLOAD_STATUS.IN_PROGRESS, null);

				} catch (IOException e) {
					postProgressEvent(options.getClientId(), getByteCount(), totalBytes, DOWNLOAD_STATUS.FAILED, e.getMessage());
					throw new KuraConnectException(e);
				} finally {
					if (is != null) {
						try {<commit_msg>Reintroduced downloading.<commit_after>/**
 * Copyright (c) 2011, 2015 Eurotech and/or its affiliates
 *
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   Eurotech
 */

package org.eclipse.kura.core.deployment.download;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.net.URLConnection;
import java.security.GeneralSecurityException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import javax.net.ssl.HttpsURLConnection;

import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.CountingOutputStream;
import org.eclipse.kura.KuraConnectException;
import org.eclipse.kura.KuraErrorCode;
import org.eclipse.kura.KuraException;
import org.eclipse.kura.core.deployment.CloudDeploymentHandlerV2.DOWNLOAD_STATUS;
import org.eclipse.kura.core.deployment.progress.ProgressEvent;
import org.eclipse.kura.core.deployment.progress.ProgressListener;
import org.eclipse.kura.ssl.SslManagerService;

public class DownloadCountingOutputStream extends CountingOutputStream {

	private static int PROP_RESOLUTION = 1024 * 4;
	private static int PROP_BUFFER_SIZE = 1024 * 4;
	private static int PROP_CONNECT_TIMEOUT = 5000;
	private static int PROP_READ_TIMEOUT = 6000;
	private static int PROP_BLOCK_DELAY = 1000;

	private final DeploymentPackageDownloadOptions options;
	// https://s3.amazonaws.com/kura-resources/dps/heater.dp

	private long totalBytes;

	private final SslManagerService m_sslManagerService;

	private final ProgressListener pl;

	InputStream is = null;

	private long m_currentStep = 1;
	
	private ExecutorService executor;
	private Future<Void> future;
	private long previous;
	private DOWNLOAD_STATUS m_downloadStatus = DOWNLOAD_STATUS.FAILED;
	

	public DownloadCountingOutputStream(OutputStream out, DeploymentPackageDownloadOptions options, ProgressListener callback,
			SslManagerService m_sslManagerService) {
		super(out);
		this.options = options;
		this.m_sslManagerService = m_sslManagerService;
		this.pl = callback;
		PROP_BUFFER_SIZE = options.getBlockSize();
		PROP_RESOLUTION = options.getNotifyBlockSize();
		PROP_BLOCK_DELAY = options.getBlockDelay();
		PROP_CONNECT_TIMEOUT = options.getTimeout();
	}

	public void setResolution(int resolution) {
		PROP_RESOLUTION = resolution;
	}

	public void setBufferSize(int size) {
		PROP_BUFFER_SIZE = size;
	}

	public void setConnectTimeout(int timeout) {
		PROP_CONNECT_TIMEOUT = timeout;
	}

	public void setReadTimeout(int timeout) {
		PROP_READ_TIMEOUT = timeout;
	}

	public void cancelDownload() throws Exception{
		if(executor != null){
			if(future != null){
				future.cancel(true);
				executor.shutdownNow();
				
				postProgressEvent(options.getClientId(), getByteCount(), totalBytes, DOWNLOAD_STATUS.FAILED, "Download cancelled");
			}
		}
	}
	
	public void startWork() throws KuraException {
		
		executor = Executors.newSingleThreadExecutor();
		
		future = executor.submit(new Callable<Void>(){

			@Override
			public Void call() throws Exception {
				URL localUrl = null;
				boolean shouldAuthenticate = false;
				try {
					shouldAuthenticate = (options.getUsername() != null) && (options.getPassword() != null)
							&& !(options.getUsername().trim().isEmpty() && !(options.getPassword().trim().isEmpty()));

					if (shouldAuthenticate) {
						Authenticator.setDefault(new Authenticator() {
							protected PasswordAuthentication getPasswordAuthentication() {
								return new PasswordAuthentication(options.getUsername(), options.getPassword().toCharArray());
							}
						});
					}

					localUrl = new URL(options.getDeployUrl());
					URLConnection urlConnection = localUrl.openConnection();
					urlConnection.setConnectTimeout(PROP_CONNECT_TIMEOUT);
					urlConnection.setReadTimeout(PROP_READ_TIMEOUT);

					try {
						if (urlConnection instanceof HttpsURLConnection) {
							((HttpsURLConnection) urlConnection).setSSLSocketFactory(m_sslManagerService.getSSLSocketFactory());
						} else if (!(urlConnection instanceof HttpURLConnection)) {
							postProgressEvent(options.getClientId(), getByteCount(), totalBytes, DOWNLOAD_STATUS.FAILED, "The request URL is not supported");
							throw new KuraConnectException("Unsupported protocol!");
						}
					} catch (GeneralSecurityException e) {
						postProgressEvent(options.getClientId(), getByteCount(), totalBytes, DOWNLOAD_STATUS.FAILED, e.getMessage());
						throw new KuraConnectException(e, "Unsupported protocol!");
					}

					is = localUrl.openStream();

					String s = urlConnection.getHeaderField("Content-Length");

					totalBytes = s != null ? Integer.parseInt(s) : -1;
					postProgressEvent(options.getClientId(), 0, totalBytes, DOWNLOAD_STATUS.IN_PROGRESS, null);
					
					IOUtils.copyLarge(is, DownloadCountingOutputStream.this, new byte[PROP_BUFFER_SIZE]);

				} catch (IOException e) {
					postProgressEvent(options.getClientId(), getByteCount(), totalBytes, DOWNLOAD_STATUS.FAILED, e.getMessage());
					throw new KuraConnectException(e);
				} finally {
					if (is != null) {
						try {
{'fraction_non_alphanumeric': 0.09887906680032808, 'fraction_numerical': 0.0071083568759682855, 'mean_word_length': 4.831030818278427, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3443132', 'n_tokens_mistral': 3631, 'n_tokens_neox': 3099, 'n_words': 689}