From: shihyun.kim Date: Sun, 3 Nov 2013 09:01:56 +0000 (+0900) Subject: NET : Modify direct connection. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F93%2F11693%2F1;p=sdk%2Finstaller%2Finstall-manager.git NET : Modify direct connection. Change direct connection to http direct connection. Change-Id: I7ddf323fd07a8c2848e0f636c000508cb1b3de2f Signed-off-by: shihyun.kim --- diff --git a/InstallManager_java/src/org/tizen/installmanager/lib/Downloader.java b/InstallManager_java/src/org/tizen/installmanager/lib/Downloader.java index 379b295..ebb3685 100644 --- a/InstallManager_java/src/org/tizen/installmanager/lib/Downloader.java +++ b/InstallManager_java/src/org/tizen/installmanager/lib/Downloader.java @@ -1,981 +1,985 @@ -/* - * InstallManager - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: - * Wooyoung Cho - * Shihyun Kim - * Taeyoung Son - * Yongsung kim - * - * 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. - * - * Contributors: - * - S-Core Co., Ltd - * - */ - -package org.tizen.installmanager.lib; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.RandomAccessFile; -import java.net.Authenticator; -import java.net.ConnectException; -import java.net.HttpURLConnection; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.MalformedURLException; -import java.net.NoRouteToHostException; -import java.net.Proxy; -import java.net.SocketAddress; -import java.net.SocketException; -import java.net.SocketTimeoutException; -import java.net.URL; -import java.net.URLConnection; -import java.net.UnknownHostException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.List; -import java.util.NoSuchElementException; - -import javax.net.ssl.SSLHandshakeException; - -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; -import org.tizen.installmanager.core.Config; -import org.tizen.installmanager.core.IMFatalException; -import org.tizen.installmanager.core.InstallManager; -import org.tizen.installmanager.core.Options; -import org.tizen.installmanager.lib.ErrorController.ErrorCode; -import org.tizen.installmanager.lib.NetworkProxy.ProxyType; -import org.tizen.installmanager.lib.exception.IMNetworkConnectException; -import org.tizen.installmanager.lib.exception.IMNetworkDownloadException; -import org.tizen.installmanager.ui.dialog.LoginDlg; -import org.tizen.installmanager.util.PathUtil; -import org.tizen.installmanager.util.ResourceHandler; - -/** - * Manages downloading from url. - * - * @author Shihyun Kim - * - */ -public class Downloader { - private static final String PROTOCOL_SEPARATOR = "://"; - private static final String USER_PASSWORD_SEPARATOR = ":"; - private static final String ID_SEPARATOR = "@"; - - private static final int BUF_SIZE = 65536; - - public static final long ERROR = -1; - - private MessageDigest mDigest; - private URLConnection mConnection = null; - private static final int CONNECT_TIMEOUT = 15000; // connection timeout: 10 sec - private static final int READ_TIMEOUT = 20000; // read timeout: 20 sec - private static final int CONNECT_THREAD_JOIN_TIMEOUT = 11000; // // connection - // thread timeout: 11 - // sec - private static final int CONNECT_RETRY = 3; - private static final int FIRST_TRY = 0; - - private String mUser = ""; - private String mPassword = ""; - - private int responseCode = -1; - private String responseMessage = ""; - private long fileSize = 0; - long rangeSize = 0; - - //Http response code - public static final int HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416; - - - // proxy authentication - private static String proxyUser = ""; - private static String proxyPassword = ""; - - public Downloader() { - try { - mDigest = MessageDigest.getInstance("SHA-256"); - } catch (NoSuchAlgorithmException e) { - Log.err("Downloader No algorithm for SHA-256"); - throw new IMFatalException("No algorithm for SHA-256"); - } - } - - /** - * Downloads the url to the local path - * - * @param sUrl - * url to download - * @param localPath - * local path to save the file from the url - * @param monitor - * @return download size in bytes if success. -1 if fail. - */ - public long download(URL sUrl, String localPath, IIMProgressMonitor monitor) - throws IMNetworkConnectException, IMNetworkDownloadException{ - Log.log("Downloading: " + sUrl + " -> " + localPath); - - if (localPath == null || localPath.equals("")) { - return ERROR; - } - - if ((sUrl == null || sUrl.toExternalForm().equals(""))) { - return ERROR; - } - - File localFile = new File(localPath); - setRangeSize(localFile); - - if (!connect(sUrl) || mConnection == null) { - Log.err("Network connection error.\n" + sUrl); - - if (ErrorController.getErrorCode() == ErrorCode.HTTP_ERROR_MESSAGE_416) { - Log.err("Requested range not satisfiable."); - PathUtil.remove(localPath); - } - - return ERROR; - } - - long downloadSize = downloadFile(localPath, monitor); - - return downloadSize; - } - - private void setRangeSize(File localFile) { - //set range size. - if (localFile.exists()) { - rangeSize = localFile.length(); - } else { - rangeSize = 0; - } - } - - private long downloadFile(String localPath, IIMProgressMonitor monitor) throws IMNetworkDownloadException{ - Log.log("File download start => " + localPath); - - File destFile = new File(localPath); - if (!destFile.isAbsolute()) { - return ERROR; - } - - File parentDir = destFile.getParentFile(); - if (!parentDir.exists()) { - if (!parentDir.mkdirs()) { - Log.err("Fail to create directory ==> " + parentDir); - } - } - - RandomAccessFile output = null; - if (isDownloadFileExist(destFile)){ - return destFile.length(); - } else { - output = getOutputFile(destFile); - } - - InputStream input = getFileInputStream(); - if (input == null) { - return ERROR; - } - - byte[] buf = new byte[BUF_SIZE]; - long totalWriteSize = rangeSize; - long writeSizePerSecond = 0; - long totalFileSize = getDownloadFileSize() +rangeSize; - - long beginMS = System.currentTimeMillis(); - - makeDigest(localPath); - - try { - - if (monitor != null) { - monitor.workedDownload(rangeSize); - } - - while (totalWriteSize < totalFileSize) { - if (input.available() > 0) { - int inputReadSize = input.read(buf); - - output.write(buf, 0, inputReadSize); - - totalWriteSize += inputReadSize; - writeSizePerSecond += inputReadSize; - - if (mDigest != null) { - mDigest.update(buf, 0, inputReadSize); - } - - long endMS = System.currentTimeMillis(); - if (endMS > (beginMS + 100)) { - if (monitor != null) { - if (monitor.isCanceled()) { - ErrorController.setError(ErrorCode.CANCEL); - return ERROR; - } - monitor.workedDownload(writeSizePerSecond); - } - - writeSizePerSecond = 0; - beginMS = endMS; - } - } - - long endMS = System.currentTimeMillis(); - if (endMS > (beginMS + READ_TIMEOUT)) { - Log.err("Can not be read during 20 seconds."); - ErrorController - .setError(ErrorCode.INTERNET_CONNECTION_ERROR); - - throw new IMNetworkDownloadException(ErrorCode.INTERNET_CONNECTION_ERROR); - } - } - } catch (SocketTimeoutException e) { - Log.ExceptionLog(e); - ErrorController.setError(ErrorCode.SERVER_CONNECTION_TIME_OUT); - throw new IMNetworkDownloadException(ErrorCode.SERVER_CONNECTION_TIME_OUT); - } catch (IOException e) { - Log.ExceptionLog(e); - ErrorController.setError(ErrorCode.UNKNOWN_ERROR); - throw new IMNetworkDownloadException(ErrorCode.UNKOWN_ERROR); - } finally { - try { - if (input != null) { - input.close(); - } - } catch (IOException e) { - Log.ExceptionLog(e); - } - - try { - if (output != null) { - output.close(); - } - } catch (IOException e) { - Log.ExceptionLog(e); - } - } - - if (totalWriteSize != this.fileSize) { - Log.err("File size error occurs during the download"); - Log.err("Expected file size => " + fileSize); - Log.err("Downloaded file size => " + totalWriteSize); - - throw new IMNetworkDownloadException(ErrorCode.NETWORK_DOWNLOADED_FILE_INCORRECTLY); - } - - Log.log("Downloaded size: " + totalWriteSize); - return totalWriteSize; - } - - private InputStream getFileInputStream() { - try { - return mConnection.getInputStream(); - } catch (FileNotFoundException e) { - Log.ExceptionLog(e); - String url = mConnection.getURL().toString(); - int index = url.lastIndexOf("/"); - String errUrl = url.substring(0, index); - String errorMsg = ErrorCode.CANNOT_FIND_FILE_IN_REPOSITROY - .getErrorMessage() + "\n(URL = " + errUrl + ")"; - ErrorController.setErrorMessage(errorMsg); - return null; - } catch (SocketTimeoutException e) { - Log.ExceptionLog(e); - ErrorController.setError(ErrorCode.SERVER_CONNECTION_TIME_OUT); - return null; - } catch (NoRouteToHostException e) { - Log.ExceptionLog(e); - ErrorController.setError(ErrorCode.NO_ROUTE_TO_HOST); - Log.err(ErrorController.getErrorMessage()); - return null; - } catch (SocketException e) { - Log.ExceptionLog(e); - ErrorController.setError(ErrorCode.INTERNET_CONNECTION_ERROR); - Log.err(ErrorController.getErrorMessage()); - return null; - } catch (IOException e) { - Log.ExceptionLog(e); - if (e.getClass().toString().indexOf("FtpLoginException") >= 0) { - ErrorController.setError(ErrorCode.NOT_LOGGED_IN); - Log.err(ErrorController.getErrorMessage()); - return null; - } - - ErrorController.setError(ErrorCode.CANNOT_DOWNLOAD_FILE); - Log.err(ErrorController.getErrorMessage()); - return null; - } catch (Throwable e) { - Log.ExceptionLog(e); - ErrorController.setErrorMessage(e.getMessage()); - return null; - } - } - - /** - * file output. - * @param outputFilePath - * @return - */ - private RandomAccessFile getOutputFile(File outputFile) { - //Create new file to download or resume downloading. - if (!outputFile.exists()) { - try { - outputFile.createNewFile(); - } catch (IOException e) { - Log.ExceptionLog(e); - ErrorController.setError(ErrorCode.CANNOT_CREATE_DOWNLOAD_FILE); - return null; - } - } - - RandomAccessFile raFile = null; - try { - raFile = new RandomAccessFile(outputFile, "rw"); - } catch (FileNotFoundException e) { - Log.ExceptionLog(e); - ErrorController.setErrorMessage(e.getMessage()); - return null; - } - - try { - if (rangeSize > 0) { - raFile.seek(rangeSize); - } - } catch (IOException e) { - ErrorController.setErrorMessage(e.getMessage()); - Log.ExceptionLog(e); - ResourceHandler.closeObjectSilently(raFile); - } - - return raFile; - } - - private void makeDigest(String filePath) { - if (mDigest != null) { - mDigest.reset(); - } else { - try { - mDigest = MessageDigest.getInstance("SHA-256"); - } catch (NoSuchAlgorithmException e) { - Log.ExceptionLog(e); - return; - } - } - - if (rangeSize > 0) { - mDigest = Checksum.getSHA256(filePath); - } - } - - private boolean isDownloadFileExist(File localFile) { - if (!localFile.exists()) { - return false; - } else { - if (localFile.length() == getDownloadFileSize()) { - return true; - } else { - return false; - } - } - } - - /** - * Set user name. - * - * @param user - */ - public void setUser(String user) { - mUser = user; - } - - /** - * Set password - * - * @param password - */ - public void setPassword(String password) { - mPassword = password; - } - - /** - * Get MessageDigest instance from downloading file. - * - * @return - */ - public MessageDigest getFileChecksum() { - return mDigest; - } - - /** - * Connect to aUrl and ready to download. - * - * @param aUrl - * @return true if connect success. - */ - public boolean connect(URL aUrl) { - Log.log("Connect to " + aUrl); - - if (isAvailableURL(aUrl)) { - boolean bRet = false; - - URL url = getURLWithAuthentication(aUrl); - - for (int i = 0; i < CONNECT_RETRY; i++) { - bRet = connectWithConfiguration(url); - - if (bRet == false - && getResponseCode() == HttpURLConnection.HTTP_PROXY_AUTH) { - LoginDlg loginDialog = new LoginDlg(new Shell( - Display.getCurrent())); - - if (i == FIRST_TRY) { - loginDialog.setWarningMessage(getResponseMessage()); - } else { - loginDialog - .setWarningMessage(ErrorCode.PROXY_AUTHENTICATION_IS_WRONG - .getErrorMessage()); - } - int dRet = loginDialog.open(); - - if (dRet == 0) { - setProxyAuthentication(loginDialog.getID(), - loginDialog.getPassword()); - } else { - break; - } - } else { - break; - } - } - - return bRet; - } else { - return false; - } - } - - private boolean connectWithConfiguration(URL url) { - boolean bRet = false; - - String proxyType = Config.getInstance().getConfigFile().getProxyType(); - if (proxyType == "") { // InstallManager uses a system proxy as default. - proxyType = ProxyType.AUTOMATIC.toString(); - } - - if (proxyType.equalsIgnoreCase(ProxyType.DIRECT.toString())) { - bRet = connectWithDirectProxy(url); - } else if (proxyType.equalsIgnoreCase(ProxyType.AUTOMATIC.toString())) { - if (Options.useAutoProxy) { - bRet = connectWithAutoProxy(url); - } else { - Config.getInstance().getConfigFile().setProxyType(ProxyType.DIRECT.toString()); - bRet = connectWithDirectProxy(url); - } - } else if (proxyType.equalsIgnoreCase(ProxyType.MANUAL.toString())) { - bRet = connectWithManualProxy(url); - } else { - bRet = connectWithDirectProxy(url); - } - - return bRet; - } - - private URL getURLWithAuthentication(URL url) { - try { - if (!mUser.isEmpty() && !mPassword.equals("")) { - String fullUrl = url.getProtocol() + PROTOCOL_SEPARATOR + mUser - + USER_PASSWORD_SEPARATOR + mPassword + ID_SEPARATOR - + url.getHost() + url.getPath(); - - return new URL(fullUrl); - } else { - return url; - } - - } catch (MalformedURLException e) { - Log.ExceptionLog(e); - return url; - } catch (Throwable e) { - Log.ExceptionLog(e); - return url; - } - } - - public boolean connectWithDirectProxy(URL url) { - boolean bRet = false; - - String protocol = url.getProtocol(); - if (protocol.startsWith("file")) { - Log.log("Connect to local path."); - bRet = connectToURL(url, Proxy.NO_PROXY); - - } else { - Proxy directProxy = NetworkProxy.getHttpDirectProxy(url); - bRet = connectToURL(url, directProxy); - } - - return bRet; - } - - public boolean connectWithAutoProxy(URL url) { - boolean bRet = false; - if (NetworkProxy.useProxy) { - bRet = connectWithProxy(url); - - if (!bRet) { - bRet = connectWithDirectProxy(url); - - if (bRet) { - NetworkProxy.useProxy = false; - } - } - } else { - bRet = connectWithDirectProxy(url); - - if (!bRet) { - bRet = connectWithProxy(url); - - if (bRet) { - NetworkProxy.useProxy = true; - } - } - } - - return bRet; - } - - public boolean connectWithManualProxy(URL url) { - Log.log("Connect to url with manual proxy. => " + url); - saveProxyAuthentication(); - - String protocol = url.getProtocol(); - Config conf = InstallManager.getInstance().getConfig(); - - boolean bRet = false; - if (protocol.startsWith("file")) { - Log.log("Connect to local path."); - bRet = connectToURL(url, Proxy.NO_PROXY); - - } else { - if (!conf.hasProxy()) { - ErrorController.setInstallationSuccess(false); - throw new IMFatalException(ErrorCode.PROXY_CANNOT_FIND_SETTING); - } else { - Log.log("Connect to repository with config proxy."); - bRet = connectToURL(url, getConfigProxy()); - } - } - return bRet; - } - - /** - * Check url available. - * - * @param url - * @return - */ - public static boolean isAvailableURL(URL url) { - if (url.getProtocol().equalsIgnoreCase("file")) { - return true; - } - SocketAddress socketAddress = null; - try { - int port = url.getPort(); - if (port < 0) { - port = url.getDefaultPort(); - } - socketAddress = getSocketAddress(url.getHost(), port); - - } catch (IMFatalException e) { - Log.ExceptionLog(e); - return false; - } - - if (socketAddress == null) { - return false; - } else { - return true; - } - } - - public static boolean isAvailableURL(String host, int port) { - SocketAddress socketAddress = null; - try { - socketAddress = getSocketAddress(host, port); - - } catch (IMFatalException e) { - Log.ExceptionLog(e); - return false; - } - - if (socketAddress == null) { - return false; - } else { - return true; - } - } - - private boolean connectWithProxy(URL url) { - saveProxyAuthentication(); - - String protocol = url.getProtocol(); - Config conf = InstallManager.getInstance().getConfig(); - - boolean bRet = false; - if (protocol.startsWith("file")) { - Log.log("Connect to local path."); - bRet = connectToURL(url, Proxy.NO_PROXY); - - } else if (Options.proxy != null) { - Log.log("Connect to repository with '-proxy' option."); - bRet = connectToURL(url, getOptionalProxy()); - - } else if (conf.hasProxy()) { - Log.log("Connect to repository with config proxy."); - bRet = connectToURL(url, getConfigProxy()); - - } else { // system proxy - Log.log("Connect to repository with system proxy."); - List proxyList = NetworkProxy.getSystemProxyList(url); - - for (Proxy proxy : proxyList) { - if (bRet = connectToURL(url, proxy)) { - break; - } - } - } - - return bRet; - } - - private boolean connectToURL(final URL url, final Proxy proxy) { - - ConnectionThread connectionThread = new ConnectionThread(url, proxy); - - connectionThread.setDaemon(true); - connectionThread.start(); - - try { - connectionThread.join(CONNECT_THREAD_JOIN_TIMEOUT); - } catch (InterruptedException e) { - Log.ExceptionLog(e); - } - - if (!connectionThread.getConnectionResult()) { - return false; - } - - if (connectionThread.isAlive()) { - ErrorController.setError(ErrorCode.INTERNET_CONNECTION_ERROR); - Log.err("Cannot connect to server (URL => " + url - + "). Connection thread still alive."); - Log.err("proxy => " + proxy); - return false; - } - - if (!checkConnectionStatus(mConnection)) { - return false; - } - - fileSize = mConnection.getContentLength(); - if (fileSize < 0) { - Log.err("Cannot connect to repository(url=>" + url + ", proxy=>" - + proxy); - ErrorController.setError(ErrorCode.INTERNET_CONNECTION_ERROR); - return false; - } else { - return true; - } - } - - private boolean checkConnectionStatus(URLConnection connection) { - if (connection == null) { - return false; - } else { - String protocol = connection.getURL().getProtocol(); - if (protocol.equalsIgnoreCase("http")) { - return checkHttpConnectionStatus(connection); - } else if (protocol.equalsIgnoreCase("ftp")) { - return true; - } else { - return true; - } - } - } - - /** - * Get reponse code from connection. - * - * @return - */ - public int getResponseCode() { - return responseCode; - } - - /** - * Get reponse message from connection. - * - * @return - */ - public String getResponseMessage() { - return responseMessage; - } - - private boolean checkHttpConnectionStatus(URLConnection connection) { - HttpURLConnection httpCon = (HttpURLConnection) connection; - - try { - responseCode = httpCon.getResponseCode(); - responseMessage = httpCon.getResponseMessage(); - } catch (IOException e) { - Log.ExceptionLog(e); - ErrorController.setError(ErrorCode.INTERNET_CONNECTION_ERROR); - return false; - } - - Log.log(Integer.toString(responseCode)); - Log.log(responseMessage); - - switch (responseCode) { - case HttpURLConnection.HTTP_OK: - return true; - case HttpURLConnection.HTTP_PARTIAL : - return true; - case HttpURLConnection.HTTP_NOT_FOUND: - ErrorController.setError(ErrorCode.CANNOT_FIND_FILE_IN_REPOSITROY); - break; - case HttpURLConnection.HTTP_UNAUTHORIZED: - ErrorController.setError(ErrorCode.HTTP_ERROR_MESSAGE_401); - break; - case HttpURLConnection.HTTP_FORBIDDEN: - ErrorController.setError(ErrorCode.HTTP_ERROR_MESSAGE_403); - break; - case HttpURLConnection.HTTP_PROXY_AUTH: - ErrorController.setError(ErrorCode.HTTP_ERROR_MESSAGE_407); - break; - case Downloader.HTTP_REQUESTED_RANGE_NOT_SATISFIABLE : - ErrorController.setError(ErrorCode.HTTP_ERROR_MESSAGE_416); - break; - case -1: - Log.err("Http response code returns -1(null). It looks a Linux bug."); - ErrorController.setError(ErrorCode.INTERNET_CONNECTION_ERROR); - break; - default: - String errMsg = "Server connection failed." + "\nError message : " - + responseMessage + "(Code number=" - + Integer.toString(responseCode) + ")"; - ErrorController.setErrorMessage(errMsg); - break; - } - - return false; - } - - private Proxy getOptionalProxy() { - Config conf = InstallManager.getInstance().getConfig(); - - String[] arr = Options.proxy.split(":"); - try { - Log.log("Use user-provided proxy: " + Options.proxy); - - SocketAddress addr = getSocketAddress(arr[0], arr[1]); - - // save proxy server and port - conf.getConfigFile().setProxyServer(arr[0]); - conf.getConfigFile().setProxyPort(arr[1]); - - return new Proxy(Proxy.Type.HTTP, addr); - } catch (IllegalArgumentException e) { - Log.ExceptionLog(e); - throw new IMFatalException(ErrorCode.PROXY_SERVER_IS_WRONG); - } catch (ArrayIndexOutOfBoundsException e) { - Log.ExceptionLog(e); - throw new IMFatalException(ErrorCode.PROXY_SERVER_IS_WRONG); - } catch (IMFatalException e) { - Log.ExceptionLog(e); - throw new IMFatalException(e.getMessage() + "\n(proxy: " + arr[0] - + ":" + arr[1] + ")."); - } - } - - private Proxy getConfigProxy() { - Config conf = InstallManager.getInstance().getConfig(); - - Log.log("Use proxy specified in .conf file: " - + conf.getConfigFile().getProxyHost() + ":" - + conf.getConfigFile().getProxyPort()); - - SocketAddress addr = null; - try { - addr = getSocketAddress(conf.getConfigFile().getProxyHost(), conf - .getConfigFile().getProxyPort()); - } catch (IMFatalException e) { - throw new IMFatalException(e.getMessage() + "\n(proxy:" - + conf.getConfigFile().getProxyHost() + ":" - + conf.getConfigFile().getProxyPort() + ")."); - } - - return new Proxy(Proxy.Type.HTTP, addr); - } - - private SocketAddress getSocketAddress(String address, String port) - throws IMFatalException { - try { - return getSocketAddress(address, Integer.parseInt(port)); - } catch (NumberFormatException e) { - Log.ExceptionLog(e); - throw new IMFatalException(ErrorCode.URL_PORT_IS_WRONG); - } - } - - public static SocketAddress getSocketAddress(String address, int port) - throws IMFatalException { - SocketAddress addr = null; - try { - addr = new InetSocketAddress(InetAddress.getByName(address), port); - } catch (UnknownHostException e) { - Log.ExceptionLog(e); - - String errMsg = ErrorCode.UNKNOWN_HOST_EXCEPTION.getErrorMessage() + - "(" + address + ")"; - throw new IMFatalException(errMsg); - - } catch (IllegalArgumentException e) { - Log.ExceptionLog(e); - throw new IMFatalException(ErrorCode.URL_PORT_IS_WRONG); - - } catch (SecurityException e) { - Log.ExceptionLog(e); - - ErrorController.setErrorMessage(e.getMessage()); - throw new IMFatalException(ErrorCode.URL_SECURITY_EXCEPTION); - } - - return addr; - } - - public void saveProxyAuthentication() { - if (!proxyUser.isEmpty() && !proxyPassword.isEmpty()) { - Authenticator.setDefault(new ProxyAuthenticator(proxyUser, - proxyPassword)); - } else { - return; - } - } - - public void setProxyAuthentication(String user, String password) { - proxyUser = user; - proxyPassword = password; - } - - /** - * Get file size to download. - * - * @return - */ - public long getDownloadFileSize() { - if (fileSize <= 0) { - return mConnection.getContentLength(); - } else { - return fileSize; - } - } - - class ConnectionThread extends Thread { - URL url = null; - Proxy proxy = null; - - boolean connectionResult = false; - - public ConnectionThread(URL url, Proxy proxy) { - this.url = url; - this.proxy = proxy; - } - - public void run() { - try { - if (url != null) { - mConnection = url.openConnection(proxy); - } - - // set connetion timeout - if (mConnection != null) { - mConnection.setConnectTimeout(CONNECT_TIMEOUT); - mConnection.setReadTimeout(READ_TIMEOUT); - - if (rangeSize > 0) { - setRangeRequest(); - } - mConnection.connect(); - } else { - return; - } - - connectionResult = true; - } catch (ConnectException e) { - Log.ExceptionLog(e); - ErrorController.setError(ErrorCode.INTERNET_CONNECTION_ERROR); - - } catch (NoRouteToHostException e) { - Log.ExceptionLog(e); - ErrorController.setError(ErrorCode.INTERNET_CONNECTION_ERROR); - - } catch (SocketTimeoutException e) { - Log.ExceptionLog(e); - ErrorController.setError(ErrorCode.SERVER_CONNECTION_TIME_OUT); - - } catch (SocketException e) { - Log.ExceptionLog(e); - ErrorController.setError(ErrorCode.INTERNET_CONNECTION_ERROR); - - } catch (FileNotFoundException e) { - Log.ExceptionLog(e); - ErrorController - .setError(ErrorCode.CANNOT_FIND_FILE_IN_REPOSITROY); - - } catch (SSLHandshakeException e) { - Log.ExceptionLog(e); - ErrorController.setError(ErrorCode.NOT_SUPPORT_HTTPS_PROTOCOL); - - } catch (NoSuchElementException e) { - Log.ExceptionLog(e); - } catch (IOException e) { - Log.ExceptionLog(e); - } catch (Throwable e) { - Log.ExceptionLog(e); - } - } - - private void setRangeRequest() { - Log.log("request range size of file " + rangeSize); - - if (mConnection != null) { - mConnection.setRequestProperty("Range", "bytes=" + String.valueOf(rangeSize) + '-'); - } else { - return; - } - } - - public boolean getConnectionResult() { - return connectionResult; - } - } -} +/* + * InstallManager + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * Wooyoung Cho + * Shihyun Kim + * Taeyoung Son + * Yongsung kim + * + * 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. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +package org.tizen.installmanager.lib; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.RandomAccessFile; +import java.net.Authenticator; +import java.net.ConnectException; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.MalformedURLException; +import java.net.NoRouteToHostException; +import java.net.Proxy; +import java.net.SocketAddress; +import java.net.SocketException; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.net.URLConnection; +import java.net.UnknownHostException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.List; +import java.util.NoSuchElementException; + +import javax.net.ssl.SSLHandshakeException; + +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.tizen.installmanager.core.Config; +import org.tizen.installmanager.core.IMFatalException; +import org.tizen.installmanager.core.InstallManager; +import org.tizen.installmanager.core.Options; +import org.tizen.installmanager.lib.ErrorController.ErrorCode; +import org.tizen.installmanager.lib.NetworkProxy.ProxyType; +import org.tizen.installmanager.lib.exception.IMNetworkConnectException; +import org.tizen.installmanager.lib.exception.IMNetworkDownloadException; +import org.tizen.installmanager.ui.dialog.LoginDlg; +import org.tizen.installmanager.util.PathUtil; +import org.tizen.installmanager.util.ResourceHandler; + +/** + * Manages downloading from url. + * + * @author Shihyun Kim + * + */ +public class Downloader { + private static final String PROTOCOL_SEPARATOR = "://"; + private static final String USER_PASSWORD_SEPARATOR = ":"; + private static final String ID_SEPARATOR = "@"; + + private static final int BUF_SIZE = 65536; + + public static final long ERROR = -1; + + private MessageDigest mDigest; + private URLConnection mConnection = null; + private static final int CONNECT_TIMEOUT = 15000; // connection timeout: 10 sec + private static final int READ_TIMEOUT = 20000; // read timeout: 20 sec + private static final int CONNECT_THREAD_JOIN_TIMEOUT = 11000; // // connection + // thread timeout: 11 + // sec + private static final int CONNECT_RETRY = 3; + private static final int FIRST_TRY = 0; + + private String mUser = ""; + private String mPassword = ""; + + private int responseCode = -1; + private String responseMessage = ""; + private long fileSize = 0; + long rangeSize = 0; + + //Http response code + public static final int HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416; + + + // proxy authentication + private static String proxyUser = ""; + private static String proxyPassword = ""; + + public Downloader() { + try { + mDigest = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e) { + Log.err("Downloader No algorithm for SHA-256"); + throw new IMFatalException("No algorithm for SHA-256"); + } + } + + /** + * Downloads the url to the local path + * + * @param sUrl + * url to download + * @param localPath + * local path to save the file from the url + * @param monitor + * @return download size in bytes if success. -1 if fail. + */ + public long download(URL sUrl, String localPath, IIMProgressMonitor monitor) + throws IMNetworkConnectException, IMNetworkDownloadException{ + Log.log("Downloading: " + sUrl + " -> " + localPath); + + if (localPath == null || localPath.equals("")) { + return ERROR; + } + + if ((sUrl == null || sUrl.toExternalForm().equals(""))) { + return ERROR; + } + + File localFile = new File(localPath); + setRangeSize(localFile); + + if (!connect(sUrl) || mConnection == null) { + Log.err("Network connection error.\n" + sUrl); + + if (ErrorController.getErrorCode() == ErrorCode.HTTP_ERROR_MESSAGE_416) { + Log.err("Requested range not satisfiable."); + PathUtil.remove(localPath); + } + + return ERROR; + } + + long downloadSize = downloadFile(localPath, monitor); + + return downloadSize; + } + + private void setRangeSize(File localFile) { + //set range size. + if (localFile.exists()) { + rangeSize = localFile.length(); + } else { + rangeSize = 0; + } + } + + private long downloadFile(String localPath, IIMProgressMonitor monitor) throws IMNetworkDownloadException{ + Log.log("File download start => " + localPath); + + File destFile = new File(localPath); + if (!destFile.isAbsolute()) { + return ERROR; + } + + File parentDir = destFile.getParentFile(); + if (!parentDir.exists()) { + if (!parentDir.mkdirs()) { + Log.err("Fail to create directory ==> " + parentDir); + } + } + + RandomAccessFile output = null; + if (isDownloadFileExist(destFile)){ + return destFile.length(); + } else { + output = getOutputFile(destFile); + } + + InputStream input = getFileInputStream(); + if (input == null) { + return ERROR; + } + + byte[] buf = new byte[BUF_SIZE]; + long totalWriteSize = rangeSize; + long writeSizePerSecond = 0; + long totalFileSize = getDownloadFileSize() +rangeSize; + + long beginMS = System.currentTimeMillis(); + + makeDigest(localPath); + + try { + + if (monitor != null) { + monitor.workedDownloadSize(rangeSize); + } + + while (totalWriteSize < totalFileSize) { + if (input.available() > 0) { + int inputReadSize = input.read(buf); + + output.write(buf, 0, inputReadSize); + + totalWriteSize += inputReadSize; + writeSizePerSecond += inputReadSize; + + if (mDigest != null) { + mDigest.update(buf, 0, inputReadSize); + } + + long endMS = System.currentTimeMillis(); + if (endMS > (beginMS + 100)) { + if (monitor != null) { + if (monitor.isCanceled()) { + ErrorController.setError(ErrorCode.CANCEL); + return ERROR; + } + monitor.workedDownloadSize(writeSizePerSecond); + } + + writeSizePerSecond = 0; + beginMS = endMS; + } + } + + long endMS = System.currentTimeMillis(); + if (endMS > (beginMS + READ_TIMEOUT)) { + Log.err("Can not be read during 20 seconds."); + ErrorController + .setError(ErrorCode.INTERNET_CONNECTION_ERROR); + + throw new IMNetworkDownloadException(ErrorCode.INTERNET_CONNECTION_ERROR); + } + } + } catch (SocketTimeoutException e) { + Log.ExceptionLog(e); + ErrorController.setError(ErrorCode.SERVER_CONNECTION_TIME_OUT); + throw new IMNetworkDownloadException(ErrorCode.SERVER_CONNECTION_TIME_OUT); + } catch (IOException e) { + Log.ExceptionLog(e); + ErrorController.setError(ErrorCode.UNKNOWN_ERROR); + throw new IMNetworkDownloadException(ErrorCode.UNKOWN_ERROR); + } finally { + try { + if (input != null) { + input.close(); + } + } catch (IOException e) { + Log.ExceptionLog(e); + } + + try { + if (output != null) { + output.close(); + } + } catch (IOException e) { + Log.ExceptionLog(e); + } + } + + if (totalWriteSize != this.fileSize) { + Log.err("File size error occurs during the download"); + Log.err("Expected file size => " + fileSize); + Log.err("Downloaded file size => " + totalWriteSize); + + throw new IMNetworkDownloadException(ErrorCode.NETWORK_DOWNLOADED_FILE_INCORRECTLY); + } + + Log.log("Downloaded size: " + totalWriteSize); + return totalWriteSize; + } + + private InputStream getFileInputStream() { + try { + return mConnection.getInputStream(); + } catch (FileNotFoundException e) { + Log.ExceptionLog(e); + String url = mConnection.getURL().toString(); + int index = url.lastIndexOf("/"); + String errUrl = url.substring(0, index); + String errorMsg = ErrorCode.CANNOT_FIND_FILE_IN_REPOSITROY + .getErrorMessage() + "\n(URL = " + errUrl + ")"; + ErrorController.setErrorMessage(errorMsg); + return null; + } catch (SocketTimeoutException e) { + Log.ExceptionLog(e); + ErrorController.setError(ErrorCode.SERVER_CONNECTION_TIME_OUT); + return null; + } catch (NoRouteToHostException e) { + Log.ExceptionLog(e); + ErrorController.setError(ErrorCode.NO_ROUTE_TO_HOST); + Log.err(ErrorController.getErrorMessage()); + return null; + } catch (SocketException e) { + Log.ExceptionLog(e); + ErrorController.setError(ErrorCode.INTERNET_CONNECTION_ERROR); + Log.err(ErrorController.getErrorMessage()); + return null; + } catch (IOException e) { + Log.ExceptionLog(e); + if (e.getClass().toString().indexOf("FtpLoginException") >= 0) { + ErrorController.setError(ErrorCode.NOT_LOGGED_IN); + Log.err(ErrorController.getErrorMessage()); + return null; + } + + ErrorController.setError(ErrorCode.CANNOT_DOWNLOAD_FILE); + Log.err(ErrorController.getErrorMessage()); + return null; + } catch (Throwable e) { + Log.ExceptionLog(e); + ErrorController.setErrorMessage(e.getMessage()); + return null; + } + } + + /** + * file output. + * @param outputFilePath + * @return + */ + private RandomAccessFile getOutputFile(File outputFile) { + //Create new file to download or resume downloading. + if (!outputFile.exists()) { + try { + outputFile.createNewFile(); + } catch (IOException e) { + Log.ExceptionLog(e); + ErrorController.setError(ErrorCode.CANNOT_CREATE_DOWNLOAD_FILE); + return null; + } + } + + RandomAccessFile raFile = null; + try { + raFile = new RandomAccessFile(outputFile, "rw"); + } catch (FileNotFoundException e) { + Log.ExceptionLog(e); + ErrorController.setErrorMessage(e.getMessage()); + return null; + } + + try { + if (rangeSize > 0) { + raFile.seek(rangeSize); + } + } catch (IOException e) { + ErrorController.setErrorMessage(e.getMessage()); + Log.ExceptionLog(e); + ResourceHandler.closeObjectSilently(raFile); + } + + return raFile; + } + + private void makeDigest(String filePath) { + if (mDigest != null) { + mDigest.reset(); + } else { + try { + mDigest = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e) { + Log.ExceptionLog(e); + return; + } + } + + if (rangeSize > 0) { + mDigest = Checksum.getSHA256(filePath); + } + } + + private boolean isDownloadFileExist(File localFile) { + if (!localFile.exists()) { + return false; + } else { + if (localFile.length() == getDownloadFileSize()) { + return true; + } else { + return false; + } + } + } + + /** + * Set user name. + * + * @param user + */ + public void setUser(String user) { + mUser = user; + } + + /** + * Set password + * + * @param password + */ + public void setPassword(String password) { + mPassword = password; + } + + /** + * Get MessageDigest instance from downloading file. + * + * @return + */ + public MessageDigest getFileChecksum() { + return mDigest; + } + + /** + * Connect to aUrl and ready to download. + * + * @param aUrl + * @return true if connect success. + */ + public boolean connect(URL aUrl) { + Log.log("Connect to " + aUrl); + + if (isAvailableURL(aUrl)) { + boolean bRet = false; + + URL url = getURLWithAuthentication(aUrl); + + for (int i = 0; i < CONNECT_RETRY; i++) { + bRet = connectWithConfiguration(url); + + if (bRet == false + && getResponseCode() == HttpURLConnection.HTTP_PROXY_AUTH) { + LoginDlg loginDialog = new LoginDlg(new Shell( + Display.getCurrent())); + + if (i == FIRST_TRY) { + loginDialog.setWarningMessage(getResponseMessage()); + } else { + loginDialog + .setWarningMessage(ErrorCode.PROXY_AUTHENTICATION_IS_WRONG + .getErrorMessage()); + } + int dRet = loginDialog.open(); + + if (dRet == 0) { + setProxyAuthentication(loginDialog.getID(), + loginDialog.getPassword()); + } else { + break; + } + } else { + break; + } + } + + return bRet; + } else { + return false; + } + } + + private boolean connectWithConfiguration(URL url) { + boolean bRet = false; + + String proxyType = Config.getInstance().getConfigFile().getProxyType(); + if (proxyType == "") { // InstallManager uses a system proxy as default. + proxyType = ProxyType.AUTOMATIC.toString(); + } + + if (proxyType.equalsIgnoreCase(ProxyType.DIRECT.toString())) { + bRet = connectWithDirectProxy(url); + } else if (proxyType.equalsIgnoreCase(ProxyType.AUTOMATIC.toString())) { + if (Options.useAutoProxy) { + bRet = connectWithAutoProxy(url); + } else { + Config.getInstance().getConfigFile().setProxyType(ProxyType.DIRECT.toString()); + bRet = connectWithDirectProxy(url); + } + } else if (proxyType.equalsIgnoreCase(ProxyType.MANUAL.toString())) { + bRet = connectWithManualProxy(url); + } else { + bRet = connectWithDirectProxy(url); + } + + return bRet; + } + + private URL getURLWithAuthentication(URL url) { + try { + if (!mUser.isEmpty() && !mPassword.equals("")) { + String fullUrl = url.getProtocol() + PROTOCOL_SEPARATOR + mUser + + USER_PASSWORD_SEPARATOR + mPassword + ID_SEPARATOR + + url.getHost() + url.getPath(); + + return new URL(fullUrl); + } else { + return url; + } + + } catch (MalformedURLException e) { + Log.ExceptionLog(e); + return url; + } catch (Throwable e) { + Log.ExceptionLog(e); + return url; + } + } + + public boolean connectWithDirectProxy(URL url) { + boolean bRet = false; + + String protocol = url.getProtocol(); + if (protocol.startsWith("file")) { + Log.log("Connect to local path."); + bRet = connectToURL(url, Proxy.NO_PROXY); + + } else { + Proxy directProxy = NetworkProxy.getHttpDirectProxy(url); + bRet = connectToURL(url, directProxy); + } + + return bRet; + } + + public boolean connectWithAutoProxy(URL url) { + boolean bRet = false; + if (NetworkProxy.useProxy) { + bRet = connectWithProxy(url); + + if (!bRet) { + bRet = connectWithDirectProxy(url); + + if (bRet) { + NetworkProxy.useProxy = false; + } + } + } else { + bRet = connectWithDirectProxy(url); + + if (!bRet) { + bRet = connectWithProxy(url); + + if (bRet) { + NetworkProxy.useProxy = true; + } + } + } + + return bRet; + } + + public boolean connectWithManualProxy(URL url) { + Log.log("Connect to url with manual proxy. => " + url); + saveProxyAuthentication(); + + String protocol = url.getProtocol(); + Config conf = InstallManager.getInstance().getConfig(); + + boolean bRet = false; + if (protocol.startsWith("file")) { + Log.log("Connect to local path."); + bRet = connectToURL(url, Proxy.NO_PROXY); + + } else { + if (!conf.hasProxy()) { + ErrorController.setInstallationSuccess(false); + throw new IMFatalException(ErrorCode.PROXY_CANNOT_FIND_SETTING); + } else { + Log.log("Connect to repository with config proxy."); + bRet = connectToURL(url, getConfigProxy()); + } + } + return bRet; + } + + /** + * Check url available. + * + * @param url + * @return + */ + public static boolean isAvailableURL(URL url) { + if (url.getProtocol().equalsIgnoreCase("file")) { + return true; + } + SocketAddress socketAddress = null; + try { + int port = url.getPort(); + if (port < 0) { + port = url.getDefaultPort(); + } + socketAddress = getSocketAddress(url.getHost(), port); + + } catch (IMFatalException e) { + Log.ExceptionLog(e); + return false; + } + + if (socketAddress == null) { + return false; + } else { + return true; + } + } + + public static boolean isAvailableURL(String host, int port) { + SocketAddress socketAddress = null; + try { + socketAddress = getSocketAddress(host, port); + + } catch (IMFatalException e) { + Log.ExceptionLog(e); + return false; + } + + if (socketAddress == null) { + return false; + } else { + return true; + } + } + + private boolean connectWithProxy(URL url) { + saveProxyAuthentication(); + + String protocol = url.getProtocol(); + Config conf = InstallManager.getInstance().getConfig(); + + boolean bRet = false; + if (protocol.startsWith("file")) { + Log.log("Connect to local path."); + bRet = connectToURL(url, Proxy.NO_PROXY); + + } else if (Options.proxy != null) { + Log.log("Connect to repository with '-proxy' option."); + bRet = connectToURL(url, getOptionalProxy()); + + } else if (conf.hasProxy()) { + Log.log("Connect to repository with config proxy."); + bRet = connectToURL(url, getConfigProxy()); + + } else { // system proxy + Log.log("Connect to repository with system proxy."); + List proxyList = NetworkProxy.getSystemProxyList(url); + + for (Proxy proxy : proxyList) { + if (proxy == Proxy.NO_PROXY) { + proxy = NetworkProxy.getHttpDirectProxy(url); + } + + if (bRet = connectToURL(url, proxy)) { + break; + } + } + } + + return bRet; + } + + private boolean connectToURL(final URL url, final Proxy proxy) { + + ConnectionThread connectionThread = new ConnectionThread(url, proxy); + + connectionThread.setDaemon(true); + connectionThread.start(); + + try { + connectionThread.join(CONNECT_THREAD_JOIN_TIMEOUT); + } catch (InterruptedException e) { + Log.ExceptionLog(e); + } + + if (!connectionThread.getConnectionResult()) { + return false; + } + + if (connectionThread.isAlive()) { + ErrorController.setError(ErrorCode.INTERNET_CONNECTION_ERROR); + Log.err("Cannot connect to server (URL => " + url + + "). Connection thread still alive."); + Log.err("proxy => " + proxy); + return false; + } + + if (!checkConnectionStatus(mConnection)) { + return false; + } + + fileSize = mConnection.getContentLength(); + if (fileSize < 0) { + Log.err("Cannot connect to repository(url=>" + url + ", proxy=>" + + proxy); + ErrorController.setError(ErrorCode.INTERNET_CONNECTION_ERROR); + return false; + } else { + return true; + } + } + + private boolean checkConnectionStatus(URLConnection connection) { + if (connection == null) { + return false; + } else { + String protocol = connection.getURL().getProtocol(); + if (protocol.equalsIgnoreCase("http")) { + return checkHttpConnectionStatus(connection); + } else if (protocol.equalsIgnoreCase("ftp")) { + return true; + } else { + return true; + } + } + } + + /** + * Get reponse code from connection. + * + * @return + */ + public int getResponseCode() { + return responseCode; + } + + /** + * Get reponse message from connection. + * + * @return + */ + public String getResponseMessage() { + return responseMessage; + } + + private boolean checkHttpConnectionStatus(URLConnection connection) { + HttpURLConnection httpCon = (HttpURLConnection) connection; + + try { + responseCode = httpCon.getResponseCode(); + responseMessage = httpCon.getResponseMessage(); + } catch (IOException e) { + Log.ExceptionLog(e); + ErrorController.setError(ErrorCode.INTERNET_CONNECTION_ERROR); + return false; + } + + Log.log(Integer.toString(responseCode)); + Log.log(responseMessage); + + switch (responseCode) { + case HttpURLConnection.HTTP_OK: + return true; + case HttpURLConnection.HTTP_PARTIAL : + return true; + case HttpURLConnection.HTTP_NOT_FOUND: + ErrorController.setError(ErrorCode.CANNOT_FIND_FILE_IN_REPOSITROY); + break; + case HttpURLConnection.HTTP_UNAUTHORIZED: + ErrorController.setError(ErrorCode.HTTP_ERROR_MESSAGE_401); + break; + case HttpURLConnection.HTTP_FORBIDDEN: + ErrorController.setError(ErrorCode.HTTP_ERROR_MESSAGE_403); + break; + case HttpURLConnection.HTTP_PROXY_AUTH: + ErrorController.setError(ErrorCode.HTTP_ERROR_MESSAGE_407); + break; + case Downloader.HTTP_REQUESTED_RANGE_NOT_SATISFIABLE : + ErrorController.setError(ErrorCode.HTTP_ERROR_MESSAGE_416); + break; + case -1: + Log.err("Http response code returns -1(null). It looks a Linux bug."); + ErrorController.setError(ErrorCode.INTERNET_CONNECTION_ERROR); + break; + default: + String errMsg = "Server connection failed." + "\nError message : " + + responseMessage + "(Code number=" + + Integer.toString(responseCode) + ")"; + ErrorController.setErrorMessage(errMsg); + break; + } + + return false; + } + + private Proxy getOptionalProxy() { + Config conf = InstallManager.getInstance().getConfig(); + + String[] arr = Options.proxy.split(":"); + try { + Log.log("Use user-provided proxy: " + Options.proxy); + + SocketAddress addr = getSocketAddress(arr[0], arr[1]); + + // save proxy server and port + conf.getConfigFile().setProxyServer(arr[0]); + conf.getConfigFile().setProxyPort(arr[1]); + + return new Proxy(Proxy.Type.HTTP, addr); + } catch (IllegalArgumentException e) { + Log.ExceptionLog(e); + throw new IMFatalException(ErrorCode.PROXY_SERVER_IS_WRONG); + } catch (ArrayIndexOutOfBoundsException e) { + Log.ExceptionLog(e); + throw new IMFatalException(ErrorCode.PROXY_SERVER_IS_WRONG); + } catch (IMFatalException e) { + Log.ExceptionLog(e); + throw new IMFatalException(e.getMessage() + "\n(proxy: " + arr[0] + + ":" + arr[1] + ")."); + } + } + + private Proxy getConfigProxy() { + Config conf = InstallManager.getInstance().getConfig(); + + Log.log("Use proxy specified in .conf file: " + + conf.getConfigFile().getProxyHost() + ":" + + conf.getConfigFile().getProxyPort()); + + SocketAddress addr = null; + try { + addr = getSocketAddress(conf.getConfigFile().getProxyHost(), conf + .getConfigFile().getProxyPort()); + } catch (IMFatalException e) { + throw new IMFatalException(e.getMessage() + "\n(proxy:" + + conf.getConfigFile().getProxyHost() + ":" + + conf.getConfigFile().getProxyPort() + ")."); + } + + return new Proxy(Proxy.Type.HTTP, addr); + } + + private SocketAddress getSocketAddress(String address, String port) + throws IMFatalException { + try { + return getSocketAddress(address, Integer.parseInt(port)); + } catch (NumberFormatException e) { + Log.ExceptionLog(e); + throw new IMFatalException(ErrorCode.URL_PORT_IS_WRONG); + } + } + + public static SocketAddress getSocketAddress(String address, int port) + throws IMFatalException { + SocketAddress addr = null; + try { + addr = new InetSocketAddress(InetAddress.getByName(address), port); + } catch (UnknownHostException e) { + Log.ExceptionLog(e); + + String errMsg = ErrorCode.UNKNOWN_HOST_EXCEPTION.getErrorMessage() + + "(" + address + ")"; + throw new IMFatalException(errMsg); + + } catch (IllegalArgumentException e) { + Log.ExceptionLog(e); + throw new IMFatalException(ErrorCode.URL_PORT_IS_WRONG); + + } catch (SecurityException e) { + Log.ExceptionLog(e); + + ErrorController.setErrorMessage(e.getMessage()); + throw new IMFatalException(ErrorCode.URL_SECURITY_EXCEPTION); + } + + return addr; + } + + public void saveProxyAuthentication() { + if (!proxyUser.isEmpty() && !proxyPassword.isEmpty()) { + Authenticator.setDefault(new ProxyAuthenticator(proxyUser, + proxyPassword)); + } else { + return; + } + } + + public void setProxyAuthentication(String user, String password) { + proxyUser = user; + proxyPassword = password; + } + + /** + * Get file size to download. + * + * @return + */ + public long getDownloadFileSize() { + if (fileSize <= 0) { + return mConnection.getContentLength(); + } else { + return fileSize; + } + } + + class ConnectionThread extends Thread { + URL url = null; + Proxy proxy = null; + + boolean connectionResult = false; + + public ConnectionThread(URL url, Proxy proxy) { + this.url = url; + this.proxy = proxy; + } + + public void run() { + try { + if (url != null) { + mConnection = url.openConnection(proxy); + } + + // set connetion timeout + if (mConnection != null) { + mConnection.setConnectTimeout(CONNECT_TIMEOUT); + mConnection.setReadTimeout(READ_TIMEOUT); + + if (rangeSize > 0) { + setRangeRequest(); + } + mConnection.connect(); + } else { + return; + } + + connectionResult = true; + } catch (ConnectException e) { + Log.ExceptionLog(e); + ErrorController.setError(ErrorCode.INTERNET_CONNECTION_ERROR); + + } catch (NoRouteToHostException e) { + Log.ExceptionLog(e); + ErrorController.setError(ErrorCode.INTERNET_CONNECTION_ERROR); + + } catch (SocketTimeoutException e) { + Log.ExceptionLog(e); + ErrorController.setError(ErrorCode.SERVER_CONNECTION_TIME_OUT); + + } catch (SocketException e) { + Log.ExceptionLog(e); + ErrorController.setError(ErrorCode.INTERNET_CONNECTION_ERROR); + + } catch (FileNotFoundException e) { + Log.ExceptionLog(e); + ErrorController + .setError(ErrorCode.CANNOT_FIND_FILE_IN_REPOSITROY); + + } catch (SSLHandshakeException e) { + Log.ExceptionLog(e); + ErrorController.setError(ErrorCode.NOT_SUPPORT_HTTPS_PROTOCOL); + + } catch (NoSuchElementException e) { + Log.ExceptionLog(e); + } catch (IOException e) { + Log.ExceptionLog(e); + } catch (Throwable e) { + Log.ExceptionLog(e); + } + } + + private void setRangeRequest() { + Log.log("request range size of file " + rangeSize); + + if (mConnection != null) { + mConnection.setRequestProperty("Range", "bytes=" + String.valueOf(rangeSize) + '-'); + } else { + return; + } + } + + public boolean getConnectionResult() { + return connectionResult; + } + } +}