8287800: JFR: Incorrect error message when starting recording with missing .jfc file
Reviewed-by: mgronlun
This commit is contained in:
parent
09da87cf5c
commit
1cf83a403f
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,7 +24,6 @@
|
||||
*/
|
||||
package jdk.jfr.internal.dcmd;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.InvalidPathException;
|
||||
@ -32,7 +31,6 @@ import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.text.ParseException;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@ -53,6 +51,7 @@ import jdk.jfr.internal.SecuritySupport;
|
||||
import jdk.jfr.internal.Type;
|
||||
import jdk.jfr.internal.jfc.JFC;
|
||||
import jdk.jfr.internal.jfc.model.JFCModel;
|
||||
import jdk.jfr.internal.jfc.model.JFCModelException;
|
||||
import jdk.jfr.internal.jfc.model.XmlInput;
|
||||
|
||||
/**
|
||||
@ -229,22 +228,23 @@ final class DCmdStart extends AbstractDCmd {
|
||||
for (String configName : settings) {
|
||||
try {
|
||||
s.putAll(JFC.createKnown(configName).getSettings());
|
||||
} catch(FileNotFoundException e) {
|
||||
throw new DCmdException("Could not find settings file'" + configName + "'", e);
|
||||
} catch (IOException | ParseException e) {
|
||||
throw new DCmdException("Could not parse settings file '" + settings[0] + "'", e);
|
||||
} catch (InvalidPathException | IOException | ParseException e) {
|
||||
throw new DCmdException(JFC.formatException("Could not", e, configName), e);
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
private LinkedHashMap<String, String> configureExtended(String[] settings, ArgumentParser parser) throws DCmdException {
|
||||
List<SafePath> paths = new ArrayList<>();
|
||||
JFCModel model = new JFCModel(l -> logWarning(l));
|
||||
for (String setting : settings) {
|
||||
paths.add(JFC.createSafePath(setting));
|
||||
try {
|
||||
model.parse(JFC.createSafePath(setting));
|
||||
} catch (InvalidPathException | IOException | JFCModelException | ParseException e) {
|
||||
throw new DCmdException(JFC.formatException("Could not", e, setting), e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
JFCModel model = new JFCModel(paths, l -> logWarning(l));
|
||||
Set<String> jfcOptions = new HashSet<>();
|
||||
for (XmlInput input : model.getInputs()) {
|
||||
jfcOptions.add(input.getName());
|
||||
@ -266,13 +266,9 @@ final class DCmdStart extends AbstractDCmd {
|
||||
}
|
||||
}
|
||||
return model.getSettings();
|
||||
} catch (IllegalArgumentException iae) {
|
||||
} catch (IllegalArgumentException iae) {
|
||||
throw new DCmdException(iae.getMessage()); // spelling error, invalid value
|
||||
} catch (FileNotFoundException ioe) {
|
||||
throw new DCmdException("Could not find settings file'" + settings[0] + "'", ioe);
|
||||
} catch (IOException | ParseException e) {
|
||||
throw new DCmdException("Could not parse settings file '" + settings[0] + "'", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Instruments JDK-events on class load to reduce startup time
|
||||
@ -436,7 +432,7 @@ final class DCmdStart extends AbstractDCmd {
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
} catch (IOException | ParseException e) {
|
||||
} catch (IOException | JFCModelException | ParseException e) {
|
||||
Logger.log(LogTag.JFR_DCMD, LogLevel.DEBUG, "Could not list .jfc options for JFR.start. " + e.getMessage());
|
||||
return "";
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,12 +25,13 @@
|
||||
|
||||
package jdk.jfr.internal.jfc;
|
||||
|
||||
import java.io.FileReader;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.AccessDeniedException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
@ -41,6 +42,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.jfr.Configuration;
|
||||
import jdk.jfr.internal.jfc.model.JFCModelException;
|
||||
import jdk.jfr.internal.LogLevel;
|
||||
import jdk.jfr.internal.LogTag;
|
||||
import jdk.jfr.internal.Logger;
|
||||
@ -118,7 +120,11 @@ public final class JFC {
|
||||
* @see java.lang.SecurityManager#checkRead(java.lang.String)
|
||||
*/
|
||||
public static Configuration create(String name, Reader reader) throws IOException, ParseException {
|
||||
return JFCParser.createConfiguration(name, reader);
|
||||
try {
|
||||
return JFCParser.createConfiguration(name, reader);
|
||||
} catch (ParseException pe) {
|
||||
throw new ParseException("Error reading JFC file. " + pe.getMessage(), -1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -281,6 +287,34 @@ public final class JFC {
|
||||
return new StringReader(c.content);
|
||||
}
|
||||
}
|
||||
return new FileReader(sf.toFile(), StandardCharsets.UTF_8);
|
||||
return Files.newBufferedReader(sf.toFile().toPath(), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public static String formatException(String prefix, Exception e, String input) {
|
||||
String message = prefix + " " + JFC.exceptionToVerb(e) + " file '" + input + "'";
|
||||
String details = e.getMessage();
|
||||
if (e instanceof JFCModelException m) {
|
||||
return message + ". " + details;
|
||||
}
|
||||
if (e instanceof ParseException && !details.isEmpty()) {
|
||||
return message + ". " + details;
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
private static String exceptionToVerb(Exception e) {
|
||||
if (e instanceof FileNotFoundException || e instanceof NoSuchFileException) {
|
||||
return "find";
|
||||
}
|
||||
if (e instanceof ParseException) {
|
||||
return "parse";
|
||||
}
|
||||
if (e instanceof JFCModelException) {
|
||||
return "use";
|
||||
}
|
||||
if (e instanceof AccessDeniedException) {
|
||||
return "access";
|
||||
}
|
||||
return "open"; // InvalidPath, IOException
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -54,12 +54,8 @@ final class JFCParser {
|
||||
JFCParserHandler ch = new JFCParserHandler();
|
||||
parseXML(content, ch);
|
||||
return PrivateAccess.getInstance().newConfiguration(name, ch.label, ch.description, ch.provider, ch.settings, content);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
throw new ParseException(iae.getMessage(), -1);
|
||||
} catch (SAXException e) {
|
||||
ParseException pe = new ParseException("Error reading JFC file. " + e.getMessage(), -1);
|
||||
pe.initCause(e);
|
||||
throw pe;
|
||||
} catch (IllegalArgumentException | SAXException e) {
|
||||
throw new ParseException(e.getMessage(), -1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,7 +65,7 @@ final class JFCParser {
|
||||
parser.parse(new InputSource(r), ch);
|
||||
}
|
||||
|
||||
private static String readContent(Reader r) throws IOException {
|
||||
private static String readContent(Reader r) throws IOException, ParseException {
|
||||
CharArrayWriter writer = new CharArrayWriter(1024);
|
||||
int count = 0;
|
||||
int ch;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -44,39 +44,43 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
public final class JFCModel {
|
||||
private final Map<String, List<ControlElement>> controls = new LinkedHashMap<>();
|
||||
private final XmlConfiguration configuration;
|
||||
private final Consumer<String> logger;
|
||||
|
||||
private JFCModel(XmlConfiguration configuration) throws ParseException {
|
||||
private JFCModel(XmlConfiguration configuration) throws JFCModelException {
|
||||
configuration.validate();
|
||||
this.configuration = configuration;
|
||||
this.logger = x -> { }; // Nothing to log.
|
||||
}
|
||||
|
||||
public JFCModel(Reader reader, Consumer<String> logger) throws ParseException, IOException {
|
||||
public JFCModel(Reader reader, Consumer<String> logger) throws IOException, JFCModelException, ParseException {
|
||||
this(Parser.parse(reader));
|
||||
addControls();
|
||||
wireConditions();
|
||||
wireSettings(logger);
|
||||
}
|
||||
|
||||
public JFCModel(List<SafePath> files, Consumer<String> logger) throws IOException, ParseException {
|
||||
public JFCModel(Consumer<String> logger) {
|
||||
this.configuration = new XmlConfiguration();
|
||||
this.configuration.setAttribute("version", "2.0");
|
||||
for (SafePath file : files) {
|
||||
JFCModel model = JFCModel.create(file, logger);
|
||||
for (var entry : model.controls.entrySet()) {
|
||||
String name = entry.getKey();
|
||||
// Fail-fast checks that prevents an ambiguous file to be written later
|
||||
if (controls.containsKey(name)) {
|
||||
throw new ParseException("Control with '" + name + "' is declared in multiple files", 0);
|
||||
}
|
||||
controls.put(name, entry.getValue());
|
||||
}
|
||||
for (XmlElement child : model.configuration.getChildren()) {
|
||||
this.configuration.addChild(child);
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public void parse(SafePath file) throws IOException, JFCModelException, ParseException {
|
||||
JFCModel model = JFCModel.create(file, logger);
|
||||
for (var entry : model.controls.entrySet()) {
|
||||
String name = entry.getKey();
|
||||
// Fail-fast checks that prevents an ambiguous file to be written later
|
||||
if (controls.containsKey(name)) {
|
||||
throw new JFCModelException("Control with '" + name + "' is declared in multiple files");
|
||||
}
|
||||
controls.put(name, entry.getValue());
|
||||
}
|
||||
for (XmlElement child : model.configuration.getChildren()) {
|
||||
this.configuration.addChild(child);
|
||||
}
|
||||
}
|
||||
|
||||
public static JFCModel create(SafePath file, Consumer<String> logger) throws ParseException, IOException {
|
||||
public static JFCModel create(SafePath file, Consumer<String> logger) throws IOException, JFCModelException, ParseException{
|
||||
if (file.toString().equals("none")) {
|
||||
XmlConfiguration configuration = new XmlConfiguration();
|
||||
configuration.setAttribute("version", "2.0");
|
||||
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
/**
|
||||
* Signals that a JFCModel is invalid.
|
||||
*/
|
||||
public final class JFCModelException extends Exception {
|
||||
private static final long serialVersionUID = -613252344752758699L;
|
||||
|
||||
public JFCModelException(String errorMessage) {
|
||||
super(errorMessage);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -29,7 +29,6 @@ import java.io.Reader;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
import jdk.internal.org.xml.sax.Attributes;
|
||||
import jdk.internal.org.xml.sax.InputSource;
|
||||
import jdk.internal.org.xml.sax.SAXException;
|
||||
@ -45,10 +44,8 @@ final class Parser {
|
||||
ConfigurationHandler handler = new ConfigurationHandler();
|
||||
saxParser.parse(new InputSource(reader), handler);
|
||||
return handler.configuration;
|
||||
} catch (SAXException sp) {
|
||||
ParseException pe = new ParseException(sp.getMessage(), -1);
|
||||
pe.initCause(sp);
|
||||
throw pe;
|
||||
} catch (SAXException | IllegalStateException e) {
|
||||
throw new ParseException(e.getMessage(), -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,7 +24,6 @@
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@ -45,9 +44,9 @@ final class XmlCondition extends XmlExpression implements ControlElement {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateChildConstraints() throws ParseException {
|
||||
protected void validateChildConstraints() throws JFCModelException {
|
||||
if (getExpressions().size() > 1) {
|
||||
throw new ParseException("Expected <condition> to not have more than one child", -1);
|
||||
throw new JFCModelException("Expected <condition> to not have more than one child");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,7 +24,6 @@
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@ -85,10 +84,10 @@ final class XmlConfiguration extends XmlElement {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateAttributes() throws ParseException {
|
||||
protected void validateAttributes() throws JFCModelException {
|
||||
super.validateAttributes();
|
||||
if (!attribute("version").equals("2.0")) {
|
||||
throw new ParseException("Only .jfc files of version 2.0 is supported", -1);
|
||||
throw new JFCModelException("Only .jfc files of version 2.0 is supported");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,7 +24,6 @@
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -63,7 +62,7 @@ class XmlElement {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
final void validate() throws ParseException {
|
||||
final void validate() throws JFCModelException {
|
||||
validateAttributes();
|
||||
validateChildConstraints();
|
||||
validateChildren();
|
||||
@ -179,35 +178,35 @@ class XmlElement {
|
||||
return producers.get(0).evaluate();
|
||||
}
|
||||
|
||||
protected void validateAttributes() throws ParseException {
|
||||
protected void validateAttributes() throws JFCModelException {
|
||||
for (String key : attributes()) {
|
||||
if (!attributes.containsKey(key)) {
|
||||
throw new ParseException("Missing mandatory attribute '" + key + "'", 0);
|
||||
throw new JFCModelException("Missing mandatory attribute '" + key + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateChildren() throws ParseException {
|
||||
private void validateChildren() throws JFCModelException {
|
||||
for (XmlElement child : elements) {
|
||||
child.validate();
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateChildConstraints() throws ParseException {
|
||||
protected void validateChildConstraints() throws JFCModelException {
|
||||
for (Constraint c : constraints()) {
|
||||
validateConstraint(c);
|
||||
}
|
||||
}
|
||||
|
||||
private final void validateConstraint(Constraint c) throws ParseException {
|
||||
private final void validateConstraint(Constraint c) throws JFCModelException {
|
||||
int count = count(c.type());
|
||||
if (count < c.min()) {
|
||||
String elementName = Utilities.elementName(c.type());
|
||||
throw new ParseException("Missing mandatory element <" + elementName + ">", 0);
|
||||
throw new JFCModelException("Missing mandatory element <" + elementName + ">");
|
||||
}
|
||||
if (count > c.max()) {
|
||||
String elementName = Utilities.elementName(c.type());
|
||||
throw new ParseException("Too many elements of type <" + elementName + ">", 0);
|
||||
throw new JFCModelException("Too many elements of type <" + elementName + ">");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,7 +24,6 @@
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
|
||||
// Base class for <condition>, <or>, <not>, <and> and <test>
|
||||
@ -45,9 +44,9 @@ abstract class XmlExpression extends XmlElement {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateChildConstraints() throws ParseException {
|
||||
protected void validateChildConstraints() throws JFCModelException {
|
||||
if (getExpressions().size() < 2) {
|
||||
throw new ParseException("Expected + <" + getElementName() + "> to have at least two children", 0);
|
||||
throw new JFCModelException("Expected + <" + getElementName() + "> to have at least two children");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,7 +24,6 @@
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
|
||||
// Corresponds to <not>
|
||||
@ -36,9 +35,9 @@ final class XmlNot extends XmlExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateChildConstraints() throws ParseException {
|
||||
protected void validateChildConstraints() throws JFCModelException {
|
||||
if (getExpressions().size() != 1) {
|
||||
throw new ParseException("Expected <not> to have a single child", 0);
|
||||
throw new JFCModelException("Expected <not> to have a single child");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,7 +24,6 @@
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
|
||||
// Corresponds to <test>
|
||||
@ -53,17 +52,17 @@ final class XmlTest extends XmlExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateChildConstraints() throws ParseException {
|
||||
protected void validateChildConstraints() throws JFCModelException {
|
||||
if (!getExpressions().isEmpty()) {
|
||||
throw new ParseException("Expected <test> to not have child elements", 0);
|
||||
throw new JFCModelException("Expected <test> to not have child elements");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateAttributes() throws ParseException {
|
||||
protected void validateAttributes() throws JFCModelException {
|
||||
super.validateAttributes();
|
||||
if (!getOperator().equalsIgnoreCase("equal")) {
|
||||
throw new ParseException("Unknown operator '" + getOperator() + "', only supported is 'equal'", 0);
|
||||
throw new JFCModelException("Unknown operator '" + getOperator() + "', only supported is 'equal'");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -32,22 +32,23 @@ import java.nio.file.InvalidPathException;
|
||||
import java.nio.file.Path;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.jfr.internal.SecuritySupport;
|
||||
import jdk.jfr.internal.SecuritySupport.SafePath;
|
||||
import jdk.jfr.internal.jfc.JFC;
|
||||
import jdk.jfr.internal.jfc.model.AbortException;
|
||||
import jdk.jfr.internal.jfc.model.JFCModel;
|
||||
import jdk.jfr.internal.jfc.model.JFCModelException;
|
||||
import jdk.jfr.internal.jfc.model.SettingsLog;
|
||||
import jdk.jfr.internal.jfc.model.UserInterface;
|
||||
import jdk.jfr.internal.jfc.model.XmlInput;
|
||||
|
||||
final class Configure extends Command {
|
||||
private final List<SafePath> inputFiles = new ArrayList<>();
|
||||
private final List<String> inputFiles = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public List<String> getOptionSyntax() {
|
||||
@ -100,13 +101,8 @@ final class Configure extends Command {
|
||||
stream.println("The whitespace delimiter can be omitted for timespan values, i.e. 20ms. For");
|
||||
stream.println("more information about the settings syntax, see Javadoc of the jdk.jfr package.");
|
||||
ensureInputFiles();
|
||||
for (SafePath path : inputFiles) {
|
||||
try {
|
||||
String name = path.toPath().getFileName().toString();
|
||||
displayParameters(stream, path, name);
|
||||
} catch (InvalidPathException | ParseException | IOException e) {
|
||||
stream.println("Unable read options for " + path + " " + e.getMessage());
|
||||
}
|
||||
for (String name : inputFiles) {
|
||||
displayParameters(stream, name);
|
||||
}
|
||||
stream.println();
|
||||
stream.println("To run interactive configuration wizard:");
|
||||
@ -126,14 +122,19 @@ final class Configure extends Command {
|
||||
stream.println(" jfr configure --input none +Hello#enabled=true --output minimal.jfc");
|
||||
}
|
||||
|
||||
private void displayParameters(PrintStream stream, SafePath path, String name) throws ParseException, IOException {
|
||||
JFCModel parameters = JFCModel.create(path, l -> stream.println("Warning! " + l));
|
||||
private void displayParameters(PrintStream stream, String name) {
|
||||
stream.println();
|
||||
stream.println("Options for " + name + ":");
|
||||
stream.println();
|
||||
for (XmlInput input : parameters.getInputs()) {
|
||||
stream.println(" " + input.getOptionSyntax());
|
||||
stream.println();
|
||||
try {
|
||||
SafePath path = JFC.createSafePath(name);
|
||||
JFCModel parameters = JFCModel.create(path, l -> stream.println("Warning! " + l));
|
||||
for (XmlInput input : parameters.getInputs()) {
|
||||
stream.println(" " + input.getOptionSyntax());
|
||||
stream.println();
|
||||
}
|
||||
} catch (JFCModelException | InvalidPathException | ParseException | IOException e) {
|
||||
stream.println(JFC.formatException(" Could not", e, name)); // indented
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,7 +154,7 @@ final class Configure extends Command {
|
||||
}
|
||||
if (acceptOption(options, "--input")) {
|
||||
String value = options.pop();
|
||||
inputFiles.addAll(makeSafePathList(value));
|
||||
inputFiles.addAll(Arrays.asList(value.split(",")));
|
||||
}
|
||||
if (acceptOption(options, "--output")) {
|
||||
if (output != null) {
|
||||
@ -190,16 +191,23 @@ final class Configure extends Command {
|
||||
}
|
||||
|
||||
private void configure(boolean interactive, boolean log, SafePath output, Map<String, String> options) throws UserDataException {
|
||||
UserInterface ui = new UserInterface();
|
||||
if (log) {
|
||||
SettingsLog.enable();
|
||||
}
|
||||
JFCModel model = new JFCModel(l -> ui.println("Warning! " + l));
|
||||
model.setLabel("Custom");
|
||||
for (String input : inputFiles) {
|
||||
try {
|
||||
model.parse(JFC.createSafePath(input));
|
||||
} catch (InvalidPathException | IOException | JFCModelException | ParseException e) {
|
||||
throw new UserDataException(JFC.formatException("could not", e, input));
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (output == null) {
|
||||
output = new SafePath(Path.of("custom.jfc"));
|
||||
}
|
||||
UserInterface ui = new UserInterface();
|
||||
JFCModel model = new JFCModel(inputFiles, l -> ui.println("Warning! " + l));
|
||||
model.setLabel("Custom");
|
||||
if (log) {
|
||||
SettingsLog.enable();
|
||||
}
|
||||
for (var option : options.entrySet()) {
|
||||
model.configure(option.getKey(), option.getValue());
|
||||
}
|
||||
@ -227,27 +235,12 @@ final class Configure extends Command {
|
||||
throw new UserDataException("could not find file: " + ffe.getMessage());
|
||||
} catch (IOException ioe) {
|
||||
throw new UserDataException("i/o error: " + ioe.getMessage());
|
||||
} catch (ParseException pe) {
|
||||
throw new UserDataException("parsing error: " + pe.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private List<SafePath> makeSafePathList(String value) {
|
||||
List<SafePath> paths = new ArrayList<>();
|
||||
for (String name : value.split(",")) {
|
||||
paths.add(JFC.createSafePath(name));
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
|
||||
private void ensureInputFiles() throws InternalError {
|
||||
if (inputFiles.isEmpty()) {
|
||||
for (SafePath predefined : SecuritySupport.getPredefinedJFCFiles()) {
|
||||
if (predefined.toString().endsWith("default.jfc")) {
|
||||
inputFiles.add(predefined);
|
||||
}
|
||||
}
|
||||
inputFiles.add("default.jfc");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -65,7 +65,7 @@ public class JcmdAsserts {
|
||||
// }
|
||||
|
||||
public static void assertNotAbleToFindSettingsFile(OutputAnalyzer output) {
|
||||
output.shouldContain("Could not parse setting");
|
||||
output.shouldContain("Could not find file");
|
||||
}
|
||||
|
||||
public static void assertNoRecordingsAvailable(OutputAnalyzer output) {
|
||||
|
Loading…
Reference in New Issue
Block a user