1 /* 2 * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package jdk.jfr.internal.dcmd; 26 27 import java.io.IOException; 28 import java.io.PrintWriter; 29 import java.io.StringWriter; 30 import java.nio.file.InvalidPathException; 31 import java.nio.file.Path; 32 import java.time.Duration; 33 import java.util.ArrayList; 34 import java.util.Collections; 35 import java.util.List; 36 37 import jdk.jfr.FlightRecorder; 38 import jdk.jfr.Recording; 39 import jdk.jfr.internal.SecuritySupport; 40 import jdk.jfr.internal.SecuritySupport.SafePath; 41 import jdk.jfr.internal.Utils; 42 43 /** 44 * Base class for JFR diagnostic commands 45 * 46 */ 47 abstract class AbstractDCmd { 48 49 private final StringWriter result; 50 private final PrintWriter log; 51 52 protected AbstractDCmd() { 53 result = new StringWriter(); 54 log = new PrintWriter(result); 55 } 56 57 protected final FlightRecorder getFlightRecorder() { 58 return FlightRecorder.getFlightRecorder(); 59 } 60 61 public final String getResult() { 62 return result.toString(); 63 } 64 65 protected final SafePath resolvePath(String path, String errorMsg) throws DCmdException { 66 if (path == null) { 67 return null; 68 } 69 try { 70 return new SafePath(path); 71 } catch (InvalidPathException e) { 72 throw new DCmdException(e, errorMsg, ", invalid path \"" + path + "\"."); 73 } 74 } 75 76 protected final Recording findRecording(String name) throws DCmdException { 77 try { 78 return findRecordingById(Integer.parseInt(name)); 79 } catch (NumberFormatException nfe) { 80 // User specified a name, not an id. 81 return findRecordingByName(name); 82 } 83 } 84 85 protected final void reportOperationComplete(String actionPrefix, Recording r, SafePath file) { 86 print(actionPrefix); 87 print(" recording "); 88 print("\"" + r.getName() + "\""); 89 if (file != null) { 90 print(","); 91 try { 92 print(" "); 93 long bytes = SecuritySupport.getFileSize(file); 94 printBytes(bytes, " "); 95 } catch (IOException e) { 96 // Ignore, not essential 97 } 98 println(" written to:"); 99 println(); 100 printPath(file); 101 } else { 102 println("."); 103 } 104 } 105 106 protected final List<Recording> getRecordings() { 107 List<Recording> list = new ArrayList<>(getFlightRecorder().getRecordings()); 108 Collections.sort(list, (a, b) -> a.getName().compareTo(b.getName())); 109 return list; 110 } 111 112 static String quoteIfNeeded(String text) { 113 if (text.contains(" ")) { 114 return "\\\"" + text + "\\\""; 115 } else { 116 return text; 117 } 118 } 119 120 protected final void println() { 121 log.println(); 122 } 123 124 protected final void print(String s) { 125 log.print(s); 126 } 127 128 protected final void print(String s, Object... args) { 129 log.printf(s, args); 130 } 131 132 protected final void println(String s, Object... args) { 133 print(s, args); 134 println(); 135 } 136 137 protected final void printBytes(long bytes, String separation) { 138 print(Utils.formatBytes(bytes, separation)); 139 } 140 141 protected final void printTimespan(Duration timespan, String separator) { 142 print(Utils.formatTimespan(timespan, separator)); 143 } 144 145 protected final void printPath(SafePath path) { 146 if (path == null) { 147 print("N/A"); 148 return; 149 } 150 try { 151 printPath(SecuritySupport.getAbsolutePath(path).toPath()); 152 } catch (IOException ioe) { 153 printPath(path.toPath()); 154 } 155 } 156 157 protected final void printPath(Path path) { 158 try { 159 println(path.toAbsolutePath().toString()); 160 } catch (SecurityException e) { 161 // fall back on filename 162 println(path.toString()); 163 } 164 } 165 166 private Recording findRecordingById(int id) throws DCmdException { 167 for (Recording r : getFlightRecorder().getRecordings()) { 168 if (r.getId() == id) { 169 return r; 170 } 171 } 172 throw new DCmdException("Could not find %d.\n\nUse JFR.check without options to see list of all available recordings.", id); 173 } 174 175 private Recording findRecordingByName(String name) throws DCmdException { 176 for (Recording recording : getFlightRecorder().getRecordings()) { 177 if (name.equals(recording.getName())) { 178 return recording; 179 } 180 } 181 throw new DCmdException("Could not find %s.\n\nUse JFR.check without options to see list of all available recordings.", name); 182 } 183 }