Skip to content

Commit 4e708e5

Browse files
committed
8260862: JFR: New configure command for the jfr tool
Reviewed-by: mgronlun
1 parent 2593196 commit 4e708e5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+3223
-270
lines changed

src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/jfc.xsd

+3-13
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,19 @@
66

77
<xsd:complexType name="configurationType">
88
<xsd:sequence>
9-
<xsd:element minOccurs="0" maxOccurs="unbounded" name="producer" type="producerType" />
9+
<xsd:element minOccurs="0" maxOccurs="unbounded" name="event" type="eventType" />
1010
</xsd:sequence>
1111
<xsd:attribute use="required" name="version" type="xsd:decimal" />
12-
<xsd:attribute use="required" name="name" type="xsd:string" />
12+
<xsd:attribute use="required" name="label" type="xsd:string" />
1313
<xsd:attribute use="optional" name="description" type="xsd:string" default="" />
1414
<xsd:attribute use="optional" name="provider" type="xsd:string" default="" />
1515
</xsd:complexType>
1616

17-
<xsd:complexType name="producerType">
18-
<xsd:sequence>
19-
<xsd:element minOccurs="0" maxOccurs="1" name="control" type="controlType" />
20-
<xsd:element minOccurs="0" maxOccurs="unbounded" name="event" type="eventType" />
21-
</xsd:sequence>
22-
<xsd:attribute use="required" name="uri" type="xsd:anyURI" />
23-
<xsd:attribute use="optional" name="label" type="xsd:string" default="" />
24-
<xsd:attribute use="optional" name="description" type="xsd:string" default="" />
25-
</xsd:complexType>
26-
2717
<xsd:complexType name="eventType">
2818
<xsd:sequence>
2919
<xsd:element minOccurs="0" maxOccurs="unbounded" name="setting" type="settingType" />
3020
</xsd:sequence>
31-
<xsd:attribute use="required" name="path" type="xsd:string" />
21+
<xsd:attribute use="required" name="name" type="xsd:string" />
3222
<xsd:attribute use="optional" name="label" type="xsd:string" />
3323
<xsd:attribute use="optional" name="description" type="xsd:string" />
3424
</xsd:complexType>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright (c) 2021, 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.jfc.model;
26+
27+
public final class AbortException extends Exception {
28+
private static final long serialVersionUID = -2501519883611363246L;
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright (c) 2021, 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.jfc.model;
26+
27+
record Constraint(Class<? extends XmlElement> type, int min, int max) {
28+
29+
public static Constraint any(Class<? extends XmlElement> type) {
30+
return new Constraint(type, 0, Integer.MAX_VALUE);
31+
}
32+
33+
public static Constraint atLeast(Class<? extends XmlElement> type, int min) {
34+
return new Constraint(type, min, Integer.MAX_VALUE);
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright (c) 2021, 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.jfc.model;
26+
27+
// Interface for elements that can control a setting,
28+
// <condition>, <selection>, <text> and <flag>
29+
interface ControlElement {
30+
String getName();
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
/*
2+
* Copyright (c) 2021, 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.jfc.model;
26+
27+
import java.io.IOException;
28+
import java.io.PrintWriter;
29+
import java.nio.charset.Charset;
30+
import java.text.ParseException;
31+
import java.util.ArrayList;
32+
import java.util.Collections;
33+
import java.util.LinkedHashMap;
34+
import java.util.List;
35+
import java.util.Map;
36+
37+
import jdk.jfr.internal.SecuritySupport.SafePath;
38+
39+
// Holds the structure of a .jfc file similar to an XML DOM.
40+
public final class JFCModel {
41+
private final Map<String, List<ControlElement>> controls = new LinkedHashMap<>();
42+
private final XmlConfiguration configuration;
43+
44+
public JFCModel(SafePath file) throws ParseException, IOException {
45+
this.configuration = createConfiguration(file);
46+
this.configuration.validate();
47+
addControls();
48+
wireConditions();
49+
wireSettings();
50+
}
51+
52+
public JFCModel(List<SafePath> files) throws IOException, ParseException {
53+
this.configuration = new XmlConfiguration();
54+
this.configuration.setAttribute("version", "2.0");
55+
for (SafePath file : files) {
56+
JFCModel model = new JFCModel(file);
57+
for (var entry : model.controls.entrySet()) {
58+
String name = entry.getKey();
59+
// Fail-fast checks that prevents an ambiguous file to be written later
60+
if (controls.containsKey(name)) {
61+
throw new ParseException("Control with '" + name + "' is declared in multiple files", 0);
62+
}
63+
controls.put(name, entry.getValue());
64+
}
65+
for (XmlElement child : model.configuration.getChildren()) {
66+
this.configuration.addChild(child);
67+
}
68+
}
69+
}
70+
71+
public void setLabel(String label) {
72+
configuration.setAttribute("label", label);
73+
}
74+
75+
public void configure(String name, String value) {
76+
for (XmlInput i : getInputs()) {
77+
if (i.getName().equals(name)) {
78+
i.configure(value);
79+
return;
80+
}
81+
}
82+
boolean add = name.startsWith("+");
83+
if (add) {
84+
name = name.substring(1);
85+
}
86+
int index = name.indexOf("#");
87+
if (index < 1 || index == name.length() - 1) {
88+
throw new IllegalArgumentException("Option '" + name + "' doesn't exist in configuration");
89+
}
90+
XmlEvent event = configuration.getEvent(name.substring(0, index), add);
91+
String settingName = name.substring(index + 1);
92+
XmlSetting setting = event.getSetting(settingName, add);
93+
94+
if (settingName.equals("period") || settingName.equals("threshold")) {
95+
try {
96+
value = Utilities.parseTimespan(value);
97+
} catch (IllegalArgumentException iae) {
98+
// OK, no validation to allow forward compatibility.
99+
}
100+
}
101+
102+
setting.setContent(value);
103+
}
104+
105+
public void configure(UserInterface ui) throws AbortException {
106+
for (XmlInput input : getInputs()) {
107+
input.configure(ui);
108+
}
109+
}
110+
111+
public List<XmlInput> getInputs() {
112+
List<XmlInput> inputs = new ArrayList<>();
113+
for (XmlControl control : configuration.getControls()) {
114+
inputs.addAll(control.getInputs());
115+
}
116+
return inputs;
117+
}
118+
119+
public XmlConfiguration getConfiguration() {
120+
return configuration;
121+
}
122+
123+
public void saveToFile(SafePath path) throws IOException {
124+
try (PrintWriter p = new PrintWriter(path.toFile(), Charset.forName("UTF-8"))) {
125+
PrettyPrinter pp = new PrettyPrinter(p);
126+
pp.print(configuration);
127+
if (p.checkError()) {
128+
throw new IOException("Error writing " + path);
129+
}
130+
}
131+
}
132+
133+
private List<ControlElement> getControlElements(String name) {
134+
return controls.getOrDefault(name, Collections.emptyList());
135+
}
136+
137+
private void addControls() {
138+
for (var controls : configuration.getControls()) {
139+
for (var control : controls.getControlElements()) {
140+
add(control);
141+
}
142+
}
143+
}
144+
145+
private void wireConditions() {
146+
for (XmlControl control : configuration.getControls()) {
147+
for (XmlCondition condition : control.getConditions()) {
148+
for (XmlElement element : condition.getChildren()) {
149+
wireExpression(condition, element);
150+
}
151+
}
152+
}
153+
}
154+
155+
private void wireExpression(XmlElement parent, XmlElement element) {
156+
element.addListener(parent);
157+
if (element instanceof XmlTest test) {
158+
wireTest(test);
159+
}
160+
if (element instanceof XmlExpression expression) {
161+
for (XmlExpression child : expression.getExpressions()) {
162+
wireExpression(expression, child);
163+
}
164+
}
165+
}
166+
167+
private void wireTest(XmlTest test) {
168+
String name = test.getName();
169+
for (ControlElement ce : getControlElements(name)) {
170+
XmlElement control = (XmlElement) ce;
171+
control.addListener(test);
172+
}
173+
}
174+
175+
private void wireSettings() {
176+
for (XmlEvent event : configuration.getEvents()) {
177+
for (XmlSetting setting : event.getSettings()) {
178+
var controlName = setting.getControl();
179+
if (controlName.isPresent()) {
180+
List<ControlElement> controls = getControlElements(controlName.get());
181+
if (controls.isEmpty()) {
182+
System.out.println("Warning! Setting '" + setting.getFullName() + "' refers to missing control '" + controlName.get() + "'");
183+
}
184+
for (ControlElement ce : controls) {
185+
XmlElement control = (XmlElement) ce;
186+
control.addListener(setting);
187+
}
188+
}
189+
}
190+
}
191+
}
192+
193+
private void add(ControlElement control) {
194+
controls.computeIfAbsent(control.getName(), x -> new ArrayList<>()).add(control);
195+
}
196+
197+
private XmlConfiguration createConfiguration(SafePath file) throws ParseException, IOException {
198+
if (file.toString().equals("none")) {
199+
XmlConfiguration configuration = new XmlConfiguration();
200+
configuration.setAttribute("version", "2.0");
201+
configuration.setAttribute("label", "None");
202+
return configuration;
203+
}
204+
return Parser.parse(file.toPath());
205+
}
206+
}

0 commit comments

Comments
 (0)