diff --git a/boot/src/main/java/com/taobao/arthas/boot/Bootstrap.java b/boot/src/main/java/com/taobao/arthas/boot/Bootstrap.java
index 58179aeca..b74e997e4 100644
--- a/boot/src/main/java/com/taobao/arthas/boot/Bootstrap.java
+++ b/boot/src/main/java/com/taobao/arthas/boot/Bootstrap.java
@@ -24,6 +24,7 @@ import com.taobao.middleware.cli.CommandLine;
import com.taobao.middleware.cli.UsageMessageFormatter;
import com.taobao.middleware.cli.annotations.Argument;
import com.taobao.middleware.cli.annotations.CLIConfigurator;
+import com.taobao.middleware.cli.annotations.DefaultValue;
import com.taobao.middleware.cli.annotations.Description;
import com.taobao.middleware.cli.annotations.Name;
import com.taobao.middleware.cli.annotations.Option;
@@ -137,7 +138,7 @@ public class Bootstrap {
this.repoMirror = repoMirror;
}
- @Option(longName = "use-https")
+ @Option(longName = "use-https", flag = true)
@Description("Use https to download, default true")
public void setUseHttps(boolean useHttps) {
this.useHttps = useHttps;
@@ -165,7 +166,7 @@ public class Bootstrap {
return verbose;
}
- @Option(shortName = "v", longName = "verbose")
+ @Option(shortName = "v", longName = "verbose", flag = true)
@Description("Verbose, print debug info.")
public void setVerbose(boolean verbose) {
this.verbose = verbose;
@@ -274,19 +275,52 @@ public class Bootstrap {
System.getProperty("user.home") + File.separator + ".arthas" + File.separator + "lib");
arthasLibDir.mkdirs();
+ /**
+ *
+ * 1. get local latest version
+ * 2. get remote latest version
+ * 3. compare two version
+ *
+ */
List versionList = listNames(arthasLibDir);
+ Collections.sort(versionList);
+
+ String localLastestVersion = null;
+ if (!versionList.isEmpty()) {
+ localLastestVersion = versionList.get(versionList.size() - 1);
+ }
- if (versionList.isEmpty()) {
+ String remoteLastestVersion = DownloadUtils.getLastestVersion(bootStrap.getRepoMirror(),
+ bootStrap.isUseHttps());
+
+ boolean needDownload = false;
+ if (localLastestVersion == null) {
+ if (remoteLastestVersion == null) {
+ // exit
+ AnsiLog.error("Can not find Arthas under local: {} and remote: {}", arthasLibDir,
+ bootStrap.getRepoMirror());
+ System.exit(1);
+ } else {
+ needDownload = true;
+ }
+ } else {
+ if (remoteLastestVersion != null) {
+ if (localLastestVersion.compareTo(remoteLastestVersion) < 0) {
+ AnsiLog.info("local lastest version: {}, remote lastest version: {}, try to download from remote.",
+ localLastestVersion, remoteLastestVersion);
+ needDownload = true;
+ }
+ }
+ }
+ if (needDownload) {
// try to download arthas from remote server.
DownloadUtils.downArthasPackaging(bootStrap.getRepoMirror(), bootStrap.isUseHttps(),
- arthasLibDir.getAbsolutePath());
- versionList = listNames(arthasLibDir);
+ remoteLastestVersion, arthasLibDir.getAbsolutePath());
+ localLastestVersion = remoteLastestVersion;
}
- Collections.sort(versionList);
-
// get the latest version
- arthasHomeDir = new File(arthasLibDir, versionList.get(versionList.size() - 1) + File.separator + "arthas");
+ arthasHomeDir = new File(arthasLibDir, localLastestVersion + File.separator + "arthas");
}
verifyArthasHome(arthasHomeDir.getAbsolutePath());
diff --git a/boot/src/main/java/com/taobao/arthas/boot/DownloadUtils.java b/boot/src/main/java/com/taobao/arthas/boot/DownloadUtils.java
index 61c90585a..d8e5d9b5d 100644
--- a/boot/src/main/java/com/taobao/arthas/boot/DownloadUtils.java
+++ b/boot/src/main/java/com/taobao/arthas/boot/DownloadUtils.java
@@ -5,8 +5,12 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
+import java.net.URLConnection;
+import java.text.DecimalFormat;
+import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@@ -28,6 +32,8 @@ public class DownloadUtils {
private static final String MAVEN_METADATA_URL = "${REPO}/com/taobao/arthas/arthas-packaging/maven-metadata.xml";
private static final String REMOTE_DOWNLOAD_URL = "${REPO}/com/taobao/arthas/arthas-packaging/${VERSION}/arthas-packaging-${VERSION}-bin.zip";
+ private static final int CONNECTION_TIMEOUT = 3000;
+
/**
* Read release version from maven-metadata.xml
*
@@ -37,10 +43,15 @@ public class DownloadUtils {
* @throws SAXException
* @throws IOException
*/
- public static String readMavenReleaseVersion(String mavenMetaDataUrl)
- throws ParserConfigurationException, SAXException, IOException {
- InputStream inputStream = new URL(mavenMetaDataUrl).openStream();
+ public static String readMavenReleaseVersion(String mavenMetaDataUrl) {
+ InputStream inputStream = null;
try {
+ URLConnection connection = new URL(mavenMetaDataUrl).openConnection();
+ if (connection instanceof HttpURLConnection) {
+ ((HttpURLConnection) connection).setConnectTimeout(CONNECTION_TIMEOUT);
+ }
+ inputStream = connection.getInputStream();
+
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document document = dBuilder.parse(inputStream);
@@ -48,13 +59,21 @@ public class DownloadUtils {
NodeList nodeList = document.getDocumentElement().getElementsByTagName("release");
return nodeList.item(0).getTextContent();
+ } catch (Throwable t) {
+ AnsiLog.debug("Can not read release version from: " + mavenMetaDataUrl);
+ AnsiLog.debug(t);
} finally {
IOUtils.close(inputStream);
}
+ return null;
}
- public static void downArthasPackaging(String repoMirror, boolean https, String savePath)
- throws ParserConfigurationException, SAXException, IOException {
+ public static String getLastestVersion(String repoMirror, boolean https) {
+ String repoUrl = getRepoUrl(repoMirror, https);
+ return readMavenReleaseVersion(MAVEN_METADATA_URL.replace("${REPO}", repoUrl));
+ }
+
+ public static String getRepoUrl(String repoMirror, boolean https) {
repoMirror = repoMirror.trim();
String repoUrl = "";
if (repoMirror.equals("center")) {
@@ -71,8 +90,12 @@ public class DownloadUtils {
if (https && repoUrl.startsWith("http")) {
repoUrl = "https" + repoUrl.substring("http".length(), repoUrl.length());
}
+ return repoUrl;
+ }
- String arthasVersion = readMavenReleaseVersion(MAVEN_METADATA_URL.replace("${REPO}", repoUrl));
+ public static void downArthasPackaging(String repoMirror, boolean https, String arthasVersion, String savePath)
+ throws ParserConfigurationException, SAXException, IOException {
+ String repoUrl = getRepoUrl(repoMirror, https);
File unzipDir = new File(savePath, arthasVersion + File.separator + "arthas");
@@ -80,22 +103,46 @@ public class DownloadUtils {
String remoteDownloadUrl = REMOTE_DOWNLOAD_URL.replace("${REPO}", repoUrl).replace("${VERSION}", arthasVersion);
AnsiLog.info("Start download arthas from remote server: " + remoteDownloadUrl);
- saveUrl(tempFile.getAbsolutePath(), remoteDownloadUrl);
+ saveUrl(tempFile.getAbsolutePath(), remoteDownloadUrl, true);
IOUtils.unzip(tempFile.getAbsolutePath(), unzipDir.getAbsolutePath());
}
- public static void saveUrl(final String filename, final String urlString)
+ public static void saveUrl(final String filename, final String urlString, boolean printProgress)
throws MalformedURLException, IOException {
BufferedInputStream in = null;
FileOutputStream fout = null;
try {
- in = new BufferedInputStream(new URL(urlString).openStream());
+ URLConnection connection = new URL(urlString).openConnection();
+ if (connection instanceof HttpURLConnection) {
+ ((HttpURLConnection) connection).setConnectTimeout(CONNECTION_TIMEOUT);
+ }
+ in = new BufferedInputStream(connection.getInputStream());
+ List values = connection.getHeaderFields().get("Content-Length");
+ int fileSize = 0;
+ if (values != null && !values.isEmpty()) {
+ String contentLength = (String) values.get(0);
+ if (contentLength != null) {
+ // parse the length into an integer...
+ fileSize = Integer.parseInt(contentLength);
+ }
+ }
+
fout = new FileOutputStream(filename);
- final byte data[] = new byte[1024];
+ final byte data[] = new byte[1024 * 1024];
+ int totalCount = 0;
int count;
- while ((count = in.read(data, 0, 1024)) != -1) {
+ long lastPrintTime = System.currentTimeMillis();
+ while ((count = in.read(data, 0, 1024 * 1024)) != -1) {
+ totalCount += count;
+ long now = System.currentTimeMillis();
+ if (now - lastPrintTime > 3000) {
+ AnsiLog.info("File size: {}, Downloaded size: {}", formatFileSize(fileSize),
+ formatFileSize(totalCount));
+ lastPrintTime = now;
+ }
+
fout.write(data, 0, count);
}
} finally {
@@ -104,4 +151,30 @@ public class DownloadUtils {
}
}
+ private static String formatFileSize(long size) {
+ String hrSize = null;
+
+ double b = size;
+ double k = size / 1024.0;
+ double m = ((size / 1024.0) / 1024.0);
+ double g = (((size / 1024.0) / 1024.0) / 1024.0);
+ double t = ((((size / 1024.0) / 1024.0) / 1024.0) / 1024.0);
+
+ DecimalFormat dec = new DecimalFormat("0.00");
+
+ if (t > 1) {
+ hrSize = dec.format(t).concat(" TB");
+ } else if (g > 1) {
+ hrSize = dec.format(g).concat(" GB");
+ } else if (m > 1) {
+ hrSize = dec.format(m).concat(" MB");
+ } else if (k > 1) {
+ hrSize = dec.format(k).concat(" KB");
+ } else {
+ hrSize = dec.format(b).concat(" Bytes");
+ }
+
+ return hrSize;
+ }
+
}