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