From d951a2166343780b9706df7dceabf0b4cde86c2c Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Thu, 22 Nov 2018 23:25:18 +0800 Subject: [PATCH] arthas-boot support versions option. #278 --- .../com/taobao/arthas/boot/Bootstrap.java | 71 +++++++++++++++---- .../com/taobao/arthas/boot/DownloadUtils.java | 63 +++++++++++----- .../com/taobao/arthas/common/IOUtils.java | 13 ++++ 3 files changed, 119 insertions(+), 28 deletions(-) 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 37419a53c..3e8617a5a 100644 --- a/boot/src/main/java/com/taobao/arthas/boot/Bootstrap.java +++ b/boot/src/main/java/com/taobao/arthas/boot/Bootstrap.java @@ -37,16 +37,15 @@ import com.taobao.middleware.cli.annotations.Summary; */ @Name("arthas-boot") @Summary("Bootstrap Arthas") -@Description("EXAMPLES:\n" + " java -jar arthas-boot.jar \n" - + " java -jar arthas-boot.jar --target-ip 0.0.0.0\n" +@Description("EXAMPLES:\n" + " java -jar arthas-boot.jar \n" + " java -jar arthas-boot.jar --target-ip 0.0.0.0\n" + " java -jar arthas-boot.jar --telnet-port 9999 --http-port -1\n" + " java -jar arthas-boot.jar -c 'sysprop; thread' \n" + " java -jar arthas-boot.jar -f batch.as \n" + " java -jar arthas-boot.jar --use-version 3.0.5\n" - + " java -jar arthas-boot.jar --session-timeout 3600\n" - + " java -jar arthas-boot.jar --attach-only\n" - + " java -jar arthas-boot.jar --repo-mirror aliyun --use-http\n" - + "WIKI:\n" + " https://alibaba.github.io/arthas\n") + + " java -jar arthas-boot.jar --versions\n" + + " java -jar arthas-boot.jar --session-timeout 3600\n" + " java -jar arthas-boot.jar --attach-only\n" + + " java -jar arthas-boot.jar --repo-mirror aliyun --use-http\n" + "WIKI:\n" + + " https://alibaba.github.io/arthas\n") public class Bootstrap { private static final int DEFAULT_TELNET_PORT = 3658; private static final int DEFAULT_HTTP_PORT = 8563; @@ -82,6 +81,11 @@ public class Bootstrap { */ private String useVersion; + /** + * list local and remote versions + */ + private boolean versions; + /** * download from maven center repository by default */ @@ -151,6 +155,12 @@ public class Bootstrap { this.repoMirror = repoMirror; } + @Option(longName = "versions", flag = true) + @Description("List local and remote arthas versions") + public void setVersions(boolean versions) { + this.versions = versions; + } + @Option(longName = "use-http", flag = true) @Description("Enforce use http to download, default use https") public void setuseHttp(boolean useHttp) { @@ -175,10 +185,6 @@ public class Bootstrap { this.batchFile = batchFile; } - public boolean isVerbose() { - return verbose; - } - @Option(shortName = "v", longName = "verbose", flag = true) @Description("Verbose, print debug info.") public void setVerbose(boolean verbose) { @@ -188,6 +194,8 @@ public class Bootstrap { public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + String mavenMetaData = null; + Bootstrap bootStrap = new Bootstrap(); CLI cli = CLIConfigurator.define(Bootstrap.class); @@ -209,6 +217,14 @@ public class Bootstrap { System.exit(0); } + if (bootStrap.isVersions()) { + if (mavenMetaData == null) { + mavenMetaData = DownloadUtils.readMavenMetaData(bootStrap.getRepoMirror(), bootStrap.isuseHttp()); + } + System.out.println(UsageRender.render(listVersions(mavenMetaData))); + System.exit(0); + } + if (JavaVersionUtils.isJava6()) { bootStrap.setuseHttp(true); AnsiLog.debug("Java version is 1.6, only support http, set useHttp to true."); @@ -311,8 +327,11 @@ public class Bootstrap { localLastestVersion = versionList.get(versionList.size() - 1); } - String remoteLastestVersion = DownloadUtils.getLastestVersion(bootStrap.getRepoMirror(), - bootStrap.isuseHttp()); + if (mavenMetaData == null) { + mavenMetaData = DownloadUtils.readMavenMetaData(bootStrap.getRepoMirror(), bootStrap.isuseHttp()); + } + + String remoteLastestVersion = DownloadUtils.readMavenReleaseVersion(mavenMetaData); boolean needDownload = false; if (localLastestVersion == null) { @@ -409,6 +428,26 @@ public class Bootstrap { mainMethod.invoke(null, new Object[] { telnetArgs.toArray(new String[0]) }); } + private static String listVersions(String mavenMetaData) { + StringBuilder result = new StringBuilder(1024); + List versionList = listNames(ARTHAS_LIB_DIR); + Collections.sort(versionList); + + result.append("Local versions:\n"); + for (String version : versionList) { + result.append(" " + version).append('\n'); + } + result.append("Remote versions:\n"); + if (mavenMetaData != null) { + List remoteVersions = DownloadUtils.readAllMavenVersion(mavenMetaData); + Collections.reverse(remoteVersions); + for (String version : remoteVersions) { + result.append(" " + version).append('\n'); + } + } + return result.toString(); + } + private static List listNames(File dir) { List names = new ArrayList(); for (File file : dir.listFiles()) { @@ -497,4 +536,12 @@ public class Bootstrap { public Long getSessionTimeout() { return sessionTimeout; } + + public boolean isVerbose() { + return verbose; + } + + public boolean isVersions() { + return versions; + } } 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 5ad8b7f21..aacaa85fc 100644 --- a/boot/src/main/java/com/taobao/arthas/boot/DownloadUtils.java +++ b/boot/src/main/java/com/taobao/arthas/boot/DownloadUtils.java @@ -1,6 +1,7 @@ package com.taobao.arthas.boot; import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -10,6 +11,7 @@ import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.text.DecimalFormat; +import java.util.ArrayList; import java.util.List; import javax.xml.parsers.DocumentBuilder; @@ -37,18 +39,12 @@ public class DownloadUtils { /** * Read release version from maven-metadata.xml * - * @param mavenMetaDataUrl + * @param mavenMetaData * @return - * @throws ParserConfigurationException - * @throws SAXException - * @throws IOException */ - public static String readMavenReleaseVersion(String mavenMetaDataUrl) { - InputStream inputStream = null; + public static String readMavenReleaseVersion(String mavenMetaData) { try { - URLConnection connection = openURLConnection(mavenMetaDataUrl); - inputStream = connection.getInputStream(); - + ByteArrayInputStream inputStream = new ByteArrayInputStream(mavenMetaData.getBytes("UTF-8")); DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); Document document = dBuilder.parse(inputStream); @@ -56,12 +52,52 @@ public class DownloadUtils { NodeList nodeList = document.getDocumentElement().getElementsByTagName("release"); return nodeList.item(0).getTextContent(); + } catch (Exception e) { + // ignore + } + return null; + } + + /** + * Read all versions from maven-metadata.xml + * + * @param mavenMetaData + * @return + */ + public static List readAllMavenVersion(String mavenMetaData) { + List result = new ArrayList(); + try { + ByteArrayInputStream inputStream = new ByteArrayInputStream(mavenMetaData.getBytes("UTF-8")); + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + Document document = dBuilder.parse(inputStream); + + NodeList nodeList = document.getDocumentElement().getElementsByTagName("version"); + int length = nodeList.getLength(); + for (int i = 0; i < length; ++i) { + result.add(nodeList.item(i).getTextContent()); + } + } catch (Exception e) { + // ignore + } + return result; + } + + public static String readMavenMetaData(String repoMirror, boolean http) { + String repoUrl = getRepoUrl(repoMirror, http); + String metaDataUrl = MAVEN_METADATA_URL.replace("${REPO}", repoUrl); + AnsiLog.debug("Download maven-metadata.xml from: {}", repoUrl); + InputStream inputStream = null; + try { + URLConnection connection = openURLConnection(metaDataUrl); + inputStream = connection.getInputStream(); + return IOUtils.toString(inputStream); } catch (javax.net.ssl.SSLException e) { AnsiLog.error("TLS connect error, please try to use --use-http argument."); - AnsiLog.error("URL: " + mavenMetaDataUrl); + AnsiLog.error("URL: " + metaDataUrl); AnsiLog.error(e); } catch (Throwable t) { - AnsiLog.error("Can not read release version from: " + mavenMetaDataUrl); + AnsiLog.error("Can not read maven-metadata.xml from: " + metaDataUrl); AnsiLog.debug(t); } finally { IOUtils.close(inputStream); @@ -69,11 +105,6 @@ public class DownloadUtils { return null; } - public static String getLastestVersion(String repoMirror, boolean http) { - String repoUrl = getRepoUrl(repoMirror, http); - return readMavenReleaseVersion(MAVEN_METADATA_URL.replace("${REPO}", repoUrl)); - } - public static String getRepoUrl(String repoMirror, boolean http) { repoMirror = repoMirror.trim(); String repoUrl = ""; diff --git a/common/src/main/java/com/taobao/arthas/common/IOUtils.java b/common/src/main/java/com/taobao/arthas/common/IOUtils.java index 8d5b74602..a9f012dd2 100644 --- a/common/src/main/java/com/taobao/arthas/common/IOUtils.java +++ b/common/src/main/java/com/taobao/arthas/common/IOUtils.java @@ -2,14 +2,17 @@ package com.taobao.arthas.common; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; +import java.nio.charset.StandardCharsets; import java.util.Enumeration; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -21,6 +24,16 @@ import java.util.zip.ZipFile; */ public class IOUtils { + public static String toString(InputStream inputStream) throws IOException { + ByteArrayOutputStream result = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int length; + while ((length = inputStream.read(buffer)) != -1) { + result.write(buffer, 0, length); + } + return result.toString("UTF-8"); + } + public static void copy(InputStream in, OutputStream out) throws IOException { byte[] buffer = new byte[1024]; int len;