blob: 9499a33496ef0de41a17ff2d957d9db956d2ef98 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.felix.webconsole.plugins.memoryusage.internal;
import java.io.File;
import java.io.PrintStream;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import org.apache.felix.shell.Command;
class MemoryUsageCommand implements Command
{
private static final String HELP_CMD = "help";
private static final String POOLS_CMD = "pools";
private static final String DUMP_CMD = "dump";
private static final String OPT_DUMP_ALL = "-a";
private static final String LS_CMD = "ls";
private static final String RM_CMD = "rm";
private final MemoryUsageSupport support;
MemoryUsageCommand(final MemoryUsageSupport support)
{
this.support = support;
}
public void execute(String commandLine, final PrintStream out, final PrintStream err)
{
final PrintWriterPrintHelper printHelper = new PrintWriterPrintHelper(out);
// Parse the commandLine to get the mem command.
final StringTokenizer st = new StringTokenizer(commandLine);
// Ignore the invoking command.
st.nextToken();
// Try to get the mem command, default is simple memory info dump.
String command = null;
try
{
command = st.nextToken();
}
catch (Exception ex)
{
// Ignore.
}
// Perform the specified command.
if (command == null)
{
mem(printHelper);
}
else if (command.equals(HELP_CMD))
{
help(out, st);
}
else if (command.equals(POOLS_CMD))
{
pools(printHelper);
}
else if (command.equals(DUMP_CMD))
{
dump(out, st, err);
}
else if (command.equals(LS_CMD))
{
ls(printHelper);
}
else if (command.equals(RM_CMD))
{
rm(out, err, st);
}
else
{
err.println("Unknown command: " + command);
}
printHelper.flush();
}
public String getName()
{
return "mem";
}
public String getShortDescription()
{
return "Prints Java VM Memory Consumption or writes a heap dump";
}
public String getUsage()
{
return "mem help";
}
// ---------- internal
private void mem(final MemoryUsageSupport.PrintHelper printHelper)
{
support.printOverallMemory(printHelper);
}
private void pools(final MemoryUsageSupport.PrintHelper printHelper)
{
support.printMemoryPools(printHelper);
}
private void help(final PrintStream out, final StringTokenizer word)
{
String command = HELP_CMD;
if (word.hasMoreTokens())
{
command = word.nextToken();
}
if (command.equals(DUMP_CMD))
{
out.printf("%s %s [ %s ]%n", getName(), DUMP_CMD, OPT_DUMP_ALL);
out.println("This command requests a heap dump to be created. If the\n"
+ "-a option is not added, only live objects are dumped.");
}
else if (command.equals(LS_CMD))
{
out.printf("%s %s%n", getName(), LS_CMD);
out.println("This command lists all heap dumps created with the\n" + DUMP_CMD + " command.");
}
else if (command.equals(RM_CMD))
{
out.printf("%s %s <dump>%n", getName(), RM_CMD);
out.println("This command removes the indicated heap dump file.\n" + "Use the " + LS_CMD
+ " to list heap dumps which may be removed.");
}
else if (command.equals(POOLS_CMD))
{
out.printf("%s %s%n", getName(), POOLS_CMD);
out.println("This command shows information about all memory pools.");
}
else
{
out.printf("%s %s [ %s | %s | %s | %s ]%n", getName(), HELP_CMD, DUMP_CMD, LS_CMD, RM_CMD, POOLS_CMD);
out.printf("%s %s [ %s ]%n", getName(), DUMP_CMD, OPT_DUMP_ALL);
out.printf("%s %s%n", getName(), LS_CMD);
out.printf("%s %s <dump>%n", getName(), RM_CMD);
out.printf("%s %s%n", getName(), POOLS_CMD);
out.println("Using the " + getName() + " command without any arguments prints a memory use overview.");
}
}
private void dump(final PrintStream out, final StringTokenizer words, final PrintStream err)
{
String dumpTarget = null;
boolean all = false;
while (words.hasMoreTokens())
{
String word = words.nextToken();
if (OPT_DUMP_ALL.equals(word))
{
all = true;
}
else
{
dumpTarget = word;
}
}
try
{
File dumpFile = support.dumpHeap(dumpTarget, !all);
out.println("Heap dumped to " + dumpFile + " (" + dumpFile.length() + " bytes)");
}
catch (NoSuchElementException e)
{
err.println("Failed dumping the heap, JVM does not provide known mechanism to create a Heap Dump");
}
}
private void ls(final MemoryUsageSupport.PrintHelper printHelper)
{
support.listDumpFiles(printHelper);
}
private void rm(final PrintStream out, final PrintStream err, final StringTokenizer words)
{
if (words.hasMoreTokens())
{
do
{
final String name = words.nextToken();
if (support.rmDumpFile(name))
{
out.println("rm: " + name + " removed");
out.flush();
}
else
{
err.println("rm: " + name + ": No such dump file");
err.flush();
}
}
while (words.hasMoreTokens());
}
}
private static class PrintWriterPrintHelper implements MemoryUsageSupport.PrintHelper
{
private static final String INDENTS = " ";
private final PrintStream pw;
private String indent;
PrintWriterPrintHelper(final PrintStream pw)
{
this.pw = pw;
this.indent = "";
}
public void title(String title, int level)
{
pw.printf("%s%s%n", getIndent(level - 1), title);
indent = getIndent(level);
}
public void val(String value)
{
pw.printf("%s%s%n", indent, value);
}
public void keyVal(final String key, final Object value)
{
if (value == null)
{
val(key);
}
else
{
pw.printf("%s%s: %s%n", indent, key, value);
}
}
void flush()
{
pw.flush();
}
private static String getIndent(final int level)
{
if (level <= 0)
{
return "";
}
final int indent = 2 * level;
if (indent > INDENTS.length())
{
return INDENTS;
}
return INDENTS.substring(0, indent);
}
}
}