diff --git a/core/src/main/java/com/taobao/arthas/core/command/basic1000/CatCommand.java b/core/src/main/java/com/taobao/arthas/core/command/basic1000/CatCommand.java index d10efaf0c..9cb3c7fcb 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/basic1000/CatCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/basic1000/CatCommand.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.nio.charset.Charset; import java.util.List; +import com.taobao.arthas.core.command.model.CatModel; import com.alibaba.arthas.deps.org.slf4j.Logger; import com.alibaba.arthas.deps.org.slf4j.LoggerFactory; import com.taobao.arthas.core.shell.cli.Completion; @@ -24,6 +25,8 @@ public class CatCommand extends AnnotatedCommand { private static final Logger logger = LoggerFactory.getLogger(CatCommand.class); private List files; private String encoding; + private Integer sizeLimit = 128 * 1024; + private int maxSizeLimit = 8 * 1024 * 1024; @Argument(argName = "files", index = 0) @Description("files") @@ -37,37 +40,43 @@ public class CatCommand extends AnnotatedCommand { this.encoding = encoding; } + @Option(shortName = "M", longName = "sizeLimit") + @Description("Upper size limit in bytes for the result (128 * 1024 by default, the maximum value is 8 * 1024 * 1024)") + public void setSizeLimit(Integer sizeLimit) { + this.sizeLimit = sizeLimit; + } + @Override public void process(CommandProcess process) { + if (!verifyOptions(process)) { + return; + } + for (String file : files) { File f = new File(file); if (!f.exists()) { - process.write("cat " + file + ": No such file or directory\n"); - process.end(); + process.end(-1, "cat " + file + ": No such file or directory"); return; } if (f.isDirectory()) { - process.write("cat " + file + ": Is a directory\n"); - process.end(); + process.end(-1, "cat " + file + ": Is a directory"); return; } } for (String file : files) { File f = new File(file); - if (f.length() > 1024 * 1024 * 8) { - process.write("cat " + file + ": Is to large, size: " + f.length() + '\n'); - process.end(); + if (f.length() > sizeLimit) { + process.end(-1, "cat " + file + ": Is too large, size: " + f.length()); return; } try { String fileToString = FileUtils.readFileToString(f, - encoding == null ? Charset.defaultCharset() : Charset.forName(encoding)); - process.write(fileToString); + encoding == null ? Charset.defaultCharset() : Charset.forName(encoding)); + process.appendResult(new CatModel(file, fileToString)); } catch (IOException e) { logger.error("cat read file error. name: " + file, e); - process.write("cat read file error: " + e.getMessage() + '\n'); - process.end(1); + process.end(1, "cat read file error: " + e.getMessage()); return; } } @@ -75,6 +84,22 @@ public class CatCommand extends AnnotatedCommand { process.end(); } + private boolean verifyOptions(CommandProcess process) { + if (sizeLimit > maxSizeLimit) { + process.end(-1, "sizeLimit cannot be large than: " + maxSizeLimit); + return false; + } + + //目前不支持过滤,限制http请求执行的文件大小 + int maxSizeLimitOfHttp = 128 * 1024; + boolean isHttpApiRequest = !process.session().isTty(); + if (isHttpApiRequest && sizeLimit > maxSizeLimitOfHttp) { + process.end(-1, "When executing commands with http, sizeLimit cannot be large than: " + maxSizeLimitOfHttp); + return false; + } + return true; + } + @Override public void complete(Completion completion) { if (!CompletionUtils.completeFilePath(completion)) { diff --git a/core/src/main/java/com/taobao/arthas/core/command/basic1000/EchoCommand.java b/core/src/main/java/com/taobao/arthas/core/command/basic1000/EchoCommand.java index 89cc62f46..b1db3f084 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/basic1000/EchoCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/basic1000/EchoCommand.java @@ -1,6 +1,8 @@ package com.taobao.arthas.core.command.basic1000; import com.taobao.arthas.core.command.Constants; +import com.taobao.arthas.core.command.model.EchoModel; +import com.taobao.arthas.core.command.model.MessageModel; import com.taobao.arthas.core.shell.command.AnnotatedCommand; import com.taobao.arthas.core.shell.command.CommandProcess; import com.taobao.middleware.cli.annotations.Argument; @@ -30,8 +32,7 @@ public class EchoCommand extends AnnotatedCommand { @Override public void process(CommandProcess process) { if (message != null) { - process.write(message); - process.write("\n"); + process.appendResult(new EchoModel(message)); } process.end(); diff --git a/core/src/main/java/com/taobao/arthas/core/command/basic1000/HelpCommand.java b/core/src/main/java/com/taobao/arthas/core/command/basic1000/HelpCommand.java index 215c6cd8e..6e1d5f23e 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/basic1000/HelpCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/basic1000/HelpCommand.java @@ -1,5 +1,9 @@ package com.taobao.arthas.core.command.basic1000; +import com.taobao.arthas.core.command.model.ArgumentVO; +import com.taobao.arthas.core.command.model.CommandOptionVO; +import com.taobao.arthas.core.command.model.CommandVO; +import com.taobao.arthas.core.command.model.HelpModel; import com.taobao.arthas.core.shell.cli.Completion; import com.taobao.arthas.core.shell.cli.CompletionUtils; import com.taobao.arthas.core.shell.command.AnnotatedCommand; @@ -9,24 +13,15 @@ import com.taobao.arthas.core.shell.command.CommandResolver; import com.taobao.arthas.core.shell.session.Session; import com.taobao.arthas.core.util.usage.StyledUsageFormatter; import com.taobao.middleware.cli.CLI; +import com.taobao.middleware.cli.Option; import com.taobao.middleware.cli.annotations.Argument; import com.taobao.middleware.cli.annotations.Description; import com.taobao.middleware.cli.annotations.Name; import com.taobao.middleware.cli.annotations.Summary; -import com.taobao.text.Color; -import com.taobao.text.Decoration; -import com.taobao.text.Style; -import com.taobao.text.ui.Element; -import com.taobao.text.ui.LabelElement; -import com.taobao.text.ui.TableElement; -import com.taobao.text.util.RenderUtil; import java.util.ArrayList; import java.util.List; -import static com.taobao.text.ui.Element.label; -import static com.taobao.text.ui.Element.row; - /** * @author vlinux on 14/10/26. */ @@ -47,16 +42,91 @@ public class HelpCommand extends AnnotatedCommand { public void process(CommandProcess process) { List commands = allCommands(process.session()); Command targetCmd = findCommand(commands); - String message; if (targetCmd == null) { - message = RenderUtil.render(mainHelp(commands), process.width()); + process.appendResult(createHelpModel(commands)); } else { - message = commandHelp(targetCmd, process.width()); + process.appendResult(createHelpDetailModel(targetCmd)); } - process.write(message); process.end(); } + public HelpModel createHelpDetailModel(Command targetCmd) { + return new HelpModel(createCommandVO(targetCmd, true)); + } + + private HelpModel createHelpModel(List commands) { + HelpModel helpModel = new HelpModel(); + for (Command command : commands) { + if(command.cli() == null || command.cli().isHidden()){ + continue; + } + helpModel.addCommandVO(createCommandVO(command, false)); + } + return helpModel; + } + + private CommandVO createCommandVO(Command command, boolean withDetail) { + CLI cli = command.cli(); + CommandVO commandVO = new CommandVO(); + commandVO.setName(command.name()); + if (cli!=null){ + commandVO.setSummary(cli.getSummary()); + if (withDetail){ + commandVO.setCli(cli); + StyledUsageFormatter usageFormatter = new StyledUsageFormatter(null); + String usageLine = usageFormatter.computeUsageLine(null, cli); + commandVO.setUsage(usageLine); + commandVO.setDescription(cli.getDescription()); + + //以线程安全的方式遍历options + List