Skip to content
Permalink
Browse files
6875: Add agent MXBean operation to return instrumented xml configura…
…tion

Reviewed-by: hirt
  • Loading branch information
jessyec-s authored and thegreystone committed Aug 20, 2020
1 parent 3aa92e4 commit f157e54f7e2abe2495333353f76d0f34f6ed0db6
@@ -103,6 +103,7 @@
<exclude>TestDefineEventProbes.java</exclude>
<exclude>TestPermissionChecks.java</exclude>
<exclude>TestRetrieveCurrentTransforms.java</exclude>
<exclude>TestRetrieveEventProbes.java</exclude>
</excludes>
</configuration>
</plugin>
@@ -137,6 +138,19 @@
<includes>TestDefineEventProbes.java</includes>
</configuration>
</execution>
<execution>
<id>test-retrieve-event-probes</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<argLine> --add-opens java.base/jdk.internal.misc=ALL-UNNAMED
-XX:+FlightRecorder -javaagent:target/org.openjdk.jmc.agent-1.0.0-SNAPSHOT.jar
-cp target/org.openjdk.jmc.agent-1.0.0-SNAPSHOT.jar:target/test-classes/ </argLine>
<includes>TestRetrieveEventProbes.java</includes>
</configuration>
</execution>
<execution>
<id>test-retrieve-transforms</id>
<goals>
@@ -61,6 +61,21 @@ public interface TransformRegistry {
*/
Set<String> getClassNames();

/**
* Returns the currently instrumented configuration.
*
* @return an XML snippet of the configuration.
*/
String getCurrentConfiguration();

/**
* Set the current configuration that will be instrumented
*
* @param xmlDescription
* an XML snippet describing the current configuration
*/
void setCurrentConfiguration(String xmlDescription);

/**
* Modifies class information in the registry according to the xml description.
*
@@ -32,9 +32,11 @@
*/
package org.openjdk.jmc.agent.impl;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
@@ -47,6 +49,7 @@
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
@@ -89,6 +92,8 @@ public class DefaultTransformRegistry implements TransformRegistry {

private volatile boolean revertInstrumentation = false;

private String currentConfiguration = "";

private static final String PROBE_SCHEMA_XSD = "jfrprobes_schema.xsd"; //$NON-NLS-1$
private static final Schema PROBE_SCHEMA;

@@ -162,6 +167,12 @@ public static TransformRegistry from(InputStream in) throws XMLStreamException {
}
streamReader.next();
}
try {
configuration.reset();
} catch (IOException e) {
throw new XMLStreamException(e);
}
registry.setCurrentConfiguration(getXmlAsString(configuration));
return registry;
}

@@ -497,6 +508,7 @@ public Set<String> modify(String xmlDescription) {
}
streamReader.next();
}
currentConfiguration = xmlDescription;
clearAllOtherTransformData(modifiedClasses);
return modifiedClasses;
} catch (XMLStreamException xse) {
@@ -520,10 +532,22 @@ public Set<String> clearAllTransformData() {
return classNames;
}

private static String getXmlAsString(InputStream in) {
return new BufferedReader(new InputStreamReader(in)).lines().collect(Collectors.joining("\n"));
}

public Set<String> getClassNames() {
return Collections.unmodifiableSet(transformData.keySet());
}

public String getCurrentConfiguration() {
return currentConfiguration;
}

public void setCurrentConfiguration(String configuration) {
currentConfiguration = configuration;
}

public void setRevertInstrumentation(boolean shouldRevert) {
this.revertInstrumentation = shouldRevert;
}
@@ -63,6 +63,7 @@ public void defineEventProbes(String xmlDescription) throws Exception{
boolean revertAll = xmlDescription == null ? true : xmlDescription.isEmpty();
if (revertAll) {
classesToRetransformArray = retransformClasses(registry.clearAllTransformData());
registry.setCurrentConfiguration("");
} else {
Set<String> initialClasses = new HashSet<>(registry.getClassNames());
Set<String> modifiedClasses = registry.modify(xmlDescription);
@@ -107,6 +108,11 @@ public JFRTransformDescriptor[] retrieveCurrentTransforms() {
return (jfrTds.toArray(new JFRTransformDescriptor[0]));
}

public String retrieveEventProbes() {
checkSecurity();
return registry.getCurrentConfiguration();
}

private void checkSecurity() {
SecurityManager secMan = System.getSecurityManager();
if (secMan != null) {
@@ -36,7 +36,22 @@

public interface AgentControllerMXBean {

/**
* Reverts all existing instrumentation and then defines a new set of event probes to transform.
*
* @param xmlDescription
* the XML snippet describing event probes to transform.
* @throws Exception
* thrown when an event probe's specified class can not be retransformed.
*/
public void defineEventProbes(String xmlDescription) throws Exception;

/**
* Returns the most recent XML configuration that was successfully applied.
*
* @return an XML snippet of the current configuration.
*/
public String retrieveEventProbes();

public JFRTransformDescriptor[] retrieveCurrentTransforms();
}
@@ -123,6 +123,18 @@ public void testModifyNameCollision() throws XMLStreamException, IOException {
assertTrue(modifiedClassNames.size() == 1);
}

@Test
public void testModifyInvalidXml() throws XMLStreamException, IOException {
TransformRegistry registry = DefaultTransformRegistry
.from(TestToolkit.getProbesXMLFromTemplate(getTemplate(), "Modify")); //$NON-NLS-1$
assertNotNull(registry);
final String initialConfiguration = registry.getCurrentConfiguration();
final String invalidSnippet = XML_EVENT_DESCRIPTION;
Set<String> modifiedClassNames = registry.modify(invalidSnippet);
assertNull(modifiedClassNames);
assertEquals(registry.getCurrentConfiguration(), initialConfiguration);
}

@Test
public void testClearAllTransformData() throws XMLStreamException, IOException {
TransformRegistry registry = DefaultTransformRegistry
@@ -0,0 +1,89 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2020, Red Hat Inc. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The contents of this file are subject to the terms of either the Universal Permissive License
* v 1.0 as shown at http://oss.oracle.com/licenses/upl
*
* or the following license:
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions
* and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials provided with
* the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.openjdk.jmc.agent.test;

import java.lang.management.ManagementFactory;

import javax.management.JMX;
import javax.management.ObjectName;

import org.junit.Assert;
import org.junit.Test;
import org.openjdk.jmc.agent.jmx.AgentControllerMXBean;

public class TestRetrieveEventProbes {

private static final String AGENT_OBJECT_NAME = "org.openjdk.jmc.jfr.agent:type=AgentController"; //$NON-NLS-1$

private static final String XML_TEST_DESCRIPTION = "<jfragent>"
+ "<events>"
+ "<event id=\"demo.jfr.test1\">"
+ "<name>JFR Hello World Event 1 </name>"
+ "<description>Defined in the xml file and added by the agent.</description>"
+ "<path>demo/jfrhelloworldevent1</path>"
+ "<stacktrace>true</stacktrace>"
+ "<class>org.openjdk.jmc.agent.test.InstrumentMe</class>"
+ "<method>"
+ "<name>printHelloWorldJFR1</name>"
+ "<descriptor>()V</descriptor>"
+ "</method>"
+ "<location>WRAP</location>"
+ "</event>"
+ "</events>"
+ "</jfragent>";
@Test
public void testRetrieveEventProbes() throws Exception {
AgentControllerMXBean mbean = JMX.newMXBeanProxy(ManagementFactory.getPlatformMBeanServer(),
new ObjectName(AGENT_OBJECT_NAME), AgentControllerMXBean.class, false);

Assert.assertNotEquals(mbean.retrieveEventProbes(), XML_TEST_DESCRIPTION);
mbean.defineEventProbes(XML_TEST_DESCRIPTION);
Assert.assertEquals(mbean.retrieveEventProbes(), XML_TEST_DESCRIPTION);
}

@Test
public void testRetrieveInvalidConfiguration() throws Exception {
AgentControllerMXBean mbean = JMX.newMXBeanProxy(ManagementFactory.getPlatformMBeanServer(),
new ObjectName(AGENT_OBJECT_NAME), AgentControllerMXBean.class, false);

String initialConfiguration = mbean.retrieveEventProbes();
String invalidConfiguration = XML_TEST_DESCRIPTION.concat("</jfragent>");
mbean.defineEventProbes(invalidConfiguration);
Assert.assertEquals(mbean.retrieveEventProbes(), initialConfiguration);
}

public void test() {
//Dummy method for instrumentation
}
}

0 comments on commit f157e54

Please sign in to comment.