Question

I have the following dowload function. I catch some possible exceptions on the way, and store them in an Exception type variable, and after cleaning up in the finally block, I would like to re-throw the original exception (if there was one caught) or throw my own custom DownloadFailedException. The problem is that Eclipse gives me "Unhandled exception type Exception" error, because my function doesn't declare throws Exception. Is there a "nice" way to do this?

public static boolean downloadFile(String urlString, String dstPath) throws DownloadFailedException, IOException {
    if (!Settings.isNetworkAvailable()) {
        throw new NoNetworkException("Network error: no internet connection. Failed downloading " + urlString);
    }
    InputStream input = null;
    BufferedOutputStream output = null;
    int fileLength = -1;
    long total = 0;
    int statusCode = -1;
    HttpGet get = new HttpGet(urlString);
    get.setHeader("User-Agent", Settings.getUserAgent());
    get.setHeader("X-My-Id", Settings.getDeviceId());
    HttpClient client = new DefaultHttpClient();
    HttpResponse response = null;
    try {
        response = client.execute(get);
        statusCode = response.getStatusLine().getStatusCode();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (200 != statusCode) {
            throw new DownloadFailedException("http error: " + statusCode +". Failed downloading " + urlString, statusCode);
        }
    }
    if (null != response) {
        HttpEntity entity = response.getEntity();
        File tmpFile = null;
        Exception exception = null;
        try {
            InputStream is = entity.getContent();
            byte b[] = new byte[1];
            is.read(b, 0, 0);
            fileLength = (int)entity.getContentLength();
            input = new BufferedInputStream(is, 8192);
            tmpFile = new File(dstPath + ".tmp");
            tmpFile.createNewFile();
            output = new BufferedOutputStream(new FileOutputStream(tmpFile), 8192);

            byte data[] = new byte[8192];
            int count;
            while ((count = input.read(data)) != -1) {
                total += count;
                output.write(data, 0, count);
            }
        } catch (IllegalStateException e) {
            exception = e;
            e.printStackTrace();
        } catch (IOException e) {
            exception = e;
            e.printStackTrace();
        } finally {
            try {
                if (null != output) {
                    output.flush();
                    output.close();
                }
                if (null != input)
                    input.close();
            } catch (IOException e) {
                if (null == exception)
                    exception = e;
            }
            if (-1 < fileLength && total != fileLength) {
                if (null != tmpFile) {
                    tmpFile.delete();
                }
                if (null != exception) {
// HERE I WOULD LIKE TO RE-THROW THE ORIGINAl EXCEPTION
                    throw exception; // Unhandled exception type Exception
                    //also tried: exception.getClass().cast(exception);
                } else
                    throw new DownloadFailedException(urlString + ": only " + total + " bytes read out of " + fileLength);
            }
            File dstFile = new File(dstPath);
            tmpFile.renameTo(dstFile);
        }
        return true;
    }
    return false;
}

SOLUTION:

if (null != exception) {
    if (exception instanceof IllegalStateException)
        throw (IllegalStateException) exception;
    else if (exception instanceof IOException)
        throw (IOException) exception;
    else
        throw new RuntimeException(message, exception);
}
//throw new IOException("Only " + total + "bytes read from " + fileLength);
throw new DownloadFailedException(message);
Was it helpful?

Solution

Where you have:

// HERE I WOULD LIKE TO RE-THROW THE ORIGINAl EXCEPTION
throw exception; // Unhandled exception type Exception
// also tried: exception.getClass().cast(exception);

I would use this:

if(exception instanceof IOException)
    throw (IOException) exception;
else
    throw new DownloadException(exception);

Based on the situation you described and the throws clause at the end of your method, that code does what you want to do. In English, here's what that code does:

  • If you catch an Exception and it's an IOException, then you want to throw an IOException
  • If you catch an Exception and it's not an IOException, you want to throw a DownloadException (of your own creation). We wrap any non-IOException in a DownloadException so that your implementation is consistent with the throws clause on your method.
  • If you do not catch an Exception, then you want life to continue as normal

Note that you may need to add a constructor like public DownloadException(Throwable e){super(e);} to your class DownloadException (if a constructor with that signature doesn't already exist) before this will compile.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top