/* * The MIT License * * Copyright (c) 2015 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.github.olivergondza.dumpling.cli; import java.io.File; import java.io.IOException; import javax.annotation.Nonnull; import com.github.olivergondza.dumpling.factory.IllegalRuntimeStateException; import com.github.olivergondza.dumpling.factory.JmxRuntimeFactory; import com.github.olivergondza.dumpling.factory.JmxRuntimeFactory.FailedToInitializeJmxConnection; import com.github.olivergondza.dumpling.factory.PidRuntimeFactory; import com.github.olivergondza.dumpling.factory.ThreadDumpFactory; import com.github.olivergondza.dumpling.model.dump.ThreadDumpRuntime; import com.github.olivergondza.dumpling.model.jmx.JmxRuntime; final /*package*/ class Factories { final /*package*/ static class ThreadDump implements CliRuntimeFactory<ThreadDumpRuntime> { @Override public @Nonnull String getKind() { return "threaddump"; } @Override public String getDescription() { return "Parse threaddrump from file, or standard input when '-' provided as a locator."; } @Override public @Nonnull ThreadDumpRuntime createRuntime( @Nonnull String locator, @Nonnull ProcessStream process ) throws CommandFailedException { ThreadDumpFactory factory = new ThreadDumpFactory(); if ("-".equals(locator)) { // Read stdin return factory.fromStream(process.in()); } try { return factory.fromFile(new File(locator)); } catch (IOException ex) { throw new CommandFailedException(ex); } catch (IllegalRuntimeStateException ex) { throw new CommandFailedException(ex); } } } final /*package*/ static class Jmx implements CliRuntimeFactory<JmxRuntime> { @Override public @Nonnull String getKind() { return "jmx"; } @Override public String getDescription() { return "Create runtime from JMX process identified by PID or HOST:PORT combination. Credentials can be provided as USER:PASSWORD@HOST:PORT."; } @Override public @Nonnull JmxRuntime createRuntime(@Nonnull String locator, @Nonnull ProcessStream process) throws CommandFailedException { JmxRuntimeFactory factory = new JmxRuntimeFactory(); try { return factory.forConnectionString(locator); } catch (FailedToInitializeJmxConnection ex) { throw new CommandFailedException(ex); } catch (IllegalRuntimeStateException ex) { throw new CommandFailedException(ex); } } } final /*package*/ static class Pid implements CliRuntimeFactory<ThreadDumpRuntime> { @Override public @Nonnull String getKind() { return "process"; } @Override public String getDescription() { return "Create runtime from running process identified by PID."; } @Override public @Nonnull ThreadDumpRuntime createRuntime(String locator, ProcessStream streams) throws CommandFailedException { PidRuntimeFactory factory = new PidRuntimeFactory(); try { return factory.fromProcess(pid(locator)); } catch (IOException ex) { throw new CommandFailedException("Unable to invoke jstack: " + ex.getMessage(), ex); } catch (InterruptedException ex) { throw new CommandFailedException("jstack invocation interrupted: " + ex.getMessage(), ex); } catch (IllegalRuntimeStateException ex) { throw new CommandFailedException(ex); } } private int pid(String locator) { try { return Integer.parseInt(locator.trim()); } catch (NumberFormatException ex) { throw new CommandFailedException("Unable to parse '" + locator + "' as process ID", ex); } } } }