package jp.co.worksap.workspace.common.download; import static com.google.common.base.Preconditions.checkArgument; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URI; import javax.annotation.Nonnull; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Cleanup; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.HttpStatus; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.impl.client.CloseableHttpClient; import com.google.common.base.Objects; @AllArgsConstructor @Slf4j abstract class AbsHttpDownloader extends Downloader { @Nonnull @Getter(AccessLevel.PROTECTED) private final AuthenticationInfoProvider infoProvider; @Override public final boolean accept(String scheme) { return Objects.equal(scheme, "http") || Objects.equal(scheme, "https"); } @Override public final void download(URI from, File to) throws IOException { checkArgument(from.isAbsolute()); checkArgument(! from.isOpaque()); HttpHost targetHost = new HttpHost(from.getHost(), from.getPort(), from.getScheme()); HttpClientContext localContext = buildClientContextFor(targetHost); HttpGet httpGet = new HttpGet(from); @Cleanup CloseableHttpClient client = buildHttpClientFor(from); log.debug("Downloading from {}...", from); @Cleanup CloseableHttpResponse response = client.execute(targetHost, httpGet, localContext); int status = response.getStatusLine().getStatusCode(); if (status == HttpStatus.SC_OK) { HttpEntity entity = response.getEntity(); final long fileSize = entity.getContentLength(); final String fileName = from.toURL().getFile(); @Cleanup InputStream inputStream = entity.getContent(); copyToLocal(to, fileName, inputStream, fileSize); } else if (status == HttpStatus.SC_UNAUTHORIZED) { client.close(); log.info("authentication is required for {}", from); retry(from, to, response.getFirstHeader("WWW-Authenticate")); } else { throw new IllegalStateException( String.format("Unexpected status code (%d) from %s", status, from) ); } } abstract void retry(URI from, File to, Header firstHeader) throws IOException; abstract CloseableHttpClient buildHttpClientFor(URI from); abstract HttpClientContext buildClientContextFor(HttpHost targetHost); }