class SyncHttpDownloadService implements DownloadService {

    @Override
    public File fetch(URL url) throws Exception {
        HttpClient httpClient = getHttpClient();
        String uri = url.toString();
        GetMethod method = new GetMethod(uri);
        method.getParams().setParameter(HttpMethodParams.USER_AGENT, "Mobipocket/ePub Converter");
//        method.getParams().setParameter(HttpMethodParams.USER_AGENT, "Mozilla/5.0 (X11; Linux i686) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.46 Safari/536.5");
        int retryCount = 10;
        int code;
        String fileName;
        File file;
        try {
            try {

                do {
                    logger.debug("Start download " + url + " try=" + (10 - retryCount));
                    code = httpClient.executeMethod(method);
                    if (code == 503) {
                        Thread.sleep(500);
                    }
                } while (code == 503 && retryCount-- > 0);

            } catch (IOException e) {
                logger.error("Download from " + uri + " failed with exception " + e.getMessage(), e);
                method.releaseConnection();
                throw new DownloadException("Download from " + uri + " failed with exception " + e.getMessage(), e);
            }
            if (code != 200) {
                method.releaseConnection();
                throw new DownloadException("File download failed with code " + code + " from url " + uri);
            }

            InputStream sourceStream = method.getResponseBodyAsStream();

            fileName = method.getPath();

            Header responseHeader = method.getResponseHeader("Content-Disposition");
            if (responseHeader != null) {
                String value = responseHeader.getValue();
                if (value.contains("attachment; filename=\"")) {
                    fileName = value.substring("attachment; filename=\"".length(), value.length() - 1);
                }
            }

            file = createTempFile(fileName);

            OutputStream targetStream = new FileOutputStream(file);

            try {
                IOUtils.copy(sourceStream, targetStream);
            } catch (Exception e) {
                IOUtils.closeQuietly(targetStream);
                FileUtils.deleteQuietly(file);
                throw e;
            } finally {
                IOUtils.closeQuietly(sourceStream);
                IOUtils.closeQuietly(targetStream);
                method.releaseConnection();
            }
        } finally {
            method.releaseConnection();
            httpClient.getHttpConnectionManager().closeIdleConnections(0);
        }

        Header contentType = method.getResponseHeader("Content-Type");
        if ((contentType != null && "application/zip".equals(contentType.getValue())) || fileName.endsWith(".zip")) {
            file = unzip(file);
        }
        logger.debug("Downloaded " + file.getName());
        return file;
    }

}