Java tutorial
/* * (C) Copyright 2006-2017 Nuxeo SA (http://nuxeo.com/) and others. * * 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: * Nuxeo * Yannis JULIENNE */ package org.nuxeo.connect.downloads; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Map; import java.util.concurrent.ThreadPoolExecutor; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.Header; import org.apache.http.HttpStatus; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.nuxeo.connect.NuxeoConnectClient; import org.nuxeo.connect.connector.ConnectServerError; import org.nuxeo.connect.connector.http.ConnectUrlConfig; import org.nuxeo.connect.connector.http.ProxyHelper; import org.nuxeo.connect.data.DownloadingPackage; import org.nuxeo.connect.data.PackageDescriptor; import org.nuxeo.connect.identity.SecurityHeaderGenerator; import org.nuxeo.connect.update.AlreadyExistsPackageException; import org.nuxeo.connect.update.PackageException; import org.nuxeo.connect.update.PackageState; import org.nuxeo.connect.update.PackageUpdateService; /** * Implementation of the {@link DownloadingPackage} interface. Encapsulate download management : ( implements * {@link Runnable} to be used in a {@link ThreadPoolExecutor}) * * @author <a href="mailto:td@nuxeo.com">Thierry Delprat</a> */ public class LocalDownloadingPackage extends PackageDescriptor implements DownloadingPackage, Runnable { /** * Timeout until a connection is established * * @since 1.4.24 */ public static final int CONNECTION_TIMEOUT_MS = 30000; // 10s /** * Timeout for waiting for data * * @since 1.4.24 */ public static final int SO_TIMEOUT_MS = 120000; // 120s protected static final Log log = LogFactory.getLog(LocalDownloadingPackage.class); protected File file = null; private boolean completed = false; private boolean serverError = false; public LocalDownloadingPackage(PackageDescriptor descriptor) { super(descriptor); sourceUrl = ConnectUrlConfig.getDownloadBaseUrl() + descriptor.getSourceUrl(); sourceDigest = descriptor.getSourceDigest(); sourceSize = descriptor.getSourceSize(); } protected void saveStreamAsFile(InputStream in) throws IOException { ConnectDownloadManager cdm = NuxeoConnectClient.getDownloadManager(); String path = cdm.getDownloadedBundleLocalStorage(); file = new File(path, getId()); OutputStream out = null; try { out = new FileOutputStream(file); byte[] buffer = new byte[1024]; int read; while ((read = in.read(buffer)) != -1) { out.write(buffer, 0, read); } } finally { if (out != null) { out.close(); } } } @Override public int getDownloadProgress() { if (file == null || !file.exists()) { return 0; } if (getSourceSize() == 0) { return 0; } return (int) ((file.length() * 100) / getSourceSize()); } public File getFile() { return file; } @Override public boolean isDigestOk() { return false; } @Override public void run() { setPackageState(PackageState.REMOTE); HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); RequestConfig.Builder requestConfigBuilder = RequestConfig.custom().setSocketTimeout(SO_TIMEOUT_MS) .setConnectTimeout(CONNECTION_TIMEOUT_MS); CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); ProxyHelper.configureProxyIfNeeded(requestConfigBuilder, credentialsProvider, sourceUrl); httpClientBuilder.setDefaultRequestConfig(requestConfigBuilder.build()); httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); try (CloseableHttpClient httpClient = httpClientBuilder.build()) { setPackageState(PackageState.DOWNLOADING); HttpGet method = new HttpGet(sourceUrl); if (!sourceUrl.contains(ConnectUrlConfig.CONNECT_TEST_MODE_BASEURL + "test")) { // for testing Map<String, String> headers = SecurityHeaderGenerator.getHeaders(); for (String headerName : headers.keySet()) { method.addHeader(headerName, headers.get(headerName)); } } try (CloseableHttpResponse httpResponse = httpClient.execute(method)) { int rc = httpResponse.getStatusLine().getStatusCode(); switch (rc) { case HttpStatus.SC_OK: if (sourceSize == 0) { Header clheader = httpResponse.getFirstHeader("content-length"); if (clheader != null) { sourceSize = Long.parseLong(clheader.getValue()); } } InputStream in = httpResponse.getEntity().getContent(); saveStreamAsFile(in); registerDownloadedPackage(); setPackageState(PackageState.DOWNLOADED); break; case HttpStatus.SC_NOT_FOUND: throw new ConnectServerError(String.format("Package not found (%s).", rc)); case HttpStatus.SC_FORBIDDEN: throw new ConnectServerError(String.format("Access refused (%s).", rc)); case HttpStatus.SC_UNAUTHORIZED: throw new ConnectServerError(String.format("Registration required (%s).", rc)); default: serverError = true; throw new ConnectServerError(String.format("Connect server HTTP response code %s.", rc)); } } } catch (IOException e) { // Expected SocketTimeoutException or ConnectTimeoutException serverError = true; setPackageState(PackageState.REMOTE); log.debug(e, e); errorMessage = e.getMessage(); } catch (ConnectServerError e) { setPackageState(PackageState.REMOTE); log.debug(e, e); errorMessage = e.getMessage(); } finally { ConnectDownloadManager cdm = NuxeoConnectClient.getDownloadManager(); cdm.removeDownloadingPackage(getId()); completed = true; } } protected void registerDownloadedPackage() { PackageUpdateService pus = NuxeoConnectClient.getPackageUpdateService(); try { pus.addPackage(file); log.info("Added " + getId()); } catch (AlreadyExistsPackageException e) { log.error(e.getMessage()); } catch (PackageException e) { log.error(e); } } @Override public boolean isCompleted() { return completed; } @Override public boolean isServerError() { return serverError; } }