Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BYTEMAN-280 Enable a 'manager' component to be configured, that can make... #29

Merged
merged 1 commit into from
Apr 20, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
68 changes: 40 additions & 28 deletions agent/src/main/java/org/jboss/byteman/agent/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,18 @@
package org.jboss.byteman.agent;


import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.instrument.Instrumentation;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.jar.JarFile;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.io.File;
import java.io.IOException;
import java.io.FileInputStream;
import java.net.Socket;
import java.util.jar.JarFile;

/**
* agent class supplied at JVM startup to install byteman package bytecode transformer
Expand All @@ -55,7 +55,6 @@ public static void premain(String args, Instrumentation inst)
throw new Exception("Main : attempting to load Byteman agent more than once");
}
}
boolean allowRedefine = false;
boolean installPolicy = false;

if (args != null) {
Expand All @@ -71,17 +70,12 @@ public static void premain(String args, Instrumentation inst)
sysJarPaths.add(arg.substring(SYS_PREFIX.length(), arg.length()));
} else if (arg.startsWith(ADDRESS_PREFIX)) {
hostname = arg.substring(ADDRESS_PREFIX.length(), arg.length());
// setting host name forces listener on
allowRedefine = true;
} else if (arg.startsWith(PORT_PREFIX)) {
try {
port = Integer.valueOf(arg.substring(PORT_PREFIX.length(), arg.length()));
if (port <= 0) {
System.err.println("Invalid port specified [" + port + "]");
port = null;
} else {
// setting port forces listener on
allowRedefine = true;
}
} catch (Exception e) {
System.err.println("Invalid port specified [" + arg + "]. Cause: " + e);
Expand All @@ -92,18 +86,14 @@ public static void premain(String args, Instrumentation inst)
resourcescriptPaths.add(arg.substring(RESOURCE_SCRIPT_PREFIX.length(), arg.length()));
} else if (arg.startsWith(LISTENER_PREFIX)) {
String value = arg.substring(LISTENER_PREFIX.length(), arg.length());
allowRedefine = Boolean.parseBoolean(value);
// clearing listener when port or host is set should be flagged
if (!allowRedefine && (hostname != null || port != null)) {
System.err.println("listener disabled with host/port set");
if (Boolean.parseBoolean(value)) {
managerClassName = TransformListener.class.getName();
}
} else if (arg.startsWith(REDEFINE_PREFIX)) {
// this is only for backwards compatibility -- it is the same as listener
String value = arg.substring(REDEFINE_PREFIX.length(), arg.length());
allowRedefine = Boolean.parseBoolean(value);
// clearing listener when port or host is set should be flagged
if (!allowRedefine && (hostname != null || port != null)) {
System.err.println("listener disabled with host/port set");
if (Boolean.parseBoolean(value)) {
managerClassName = TransformListener.class.getName();
}
} else if (arg.startsWith(PROP_PREFIX)) {
// this can be used to set byteman properties
Expand All @@ -130,6 +120,8 @@ public static void premain(String args, Instrumentation inst)
} else if (arg.startsWith(POLICY_PREFIX)) {
String value = arg.substring(POLICY_PREFIX.length(), arg.length());
installPolicy = Boolean.parseBoolean(value);
} else if (arg.startsWith(MANAGER_PREFIX)) {
managerClassName = arg.substring(MANAGER_PREFIX.length(), arg.length());
} else {
System.err.println("org.jboss.byteman.agent.Main:\n" +
" illegal agent argument : " + arg + "\n" +
Expand Down Expand Up @@ -224,7 +216,7 @@ public static void premain(String args, Instrumentation inst)
ClassLoader loader = ClassLoader.getSystemClassLoader();
Class transformerClazz;

if (allowRedefine && isRedefine) {
if (managerClassName != null && isRedefine) {
transformerClazz = loader.loadClass("org.jboss.byteman.agent.Retransformer");
//transformer = new Retransformer(inst, scriptPaths, scripts, true);
Constructor constructor = transformerClazz.getConstructor(Instrumentation.class, List.class, List.class, boolean.class);
Expand All @@ -237,10 +229,17 @@ public static void premain(String args, Instrumentation inst)
}

inst.addTransformer(transformer, true);

if (allowRedefine && isRedefine) {
Method method = transformerClazz.getMethod("addTransformListener", String.class, Integer.class);
method.invoke(transformer, hostname, port);

if (managerClassName != null && isRedefine) {
Class managerClazz = loader.loadClass(managerClassName);

try {
Method method = managerClazz.getMethod("initialize", transformerClazz, String.class, Integer.class);
method.invoke(null, transformer, hostname, port);
} catch (NoSuchMethodException e) {
Method method = managerClazz.getMethod("initialize", transformerClazz);
method.invoke(null, transformer);
}
}

if (installPolicy) {
Expand Down Expand Up @@ -270,7 +269,7 @@ public static void agentmain(String args, Instrumentation inst) throws Exception
* prefix used to specify bind address argument for agent
*/
private static final String ADDRESS_PREFIX = "address:";

/**
* prefix used to specify boot jar argument for agent
*/
Expand Down Expand Up @@ -316,6 +315,12 @@ public static void agentmain(String args, Instrumentation inst) throws Exception

private static final String PROP_PREFIX = "prop:";

/**
* prefix used to specify the manager class
*/

private static final String MANAGER_PREFIX = "manager:";

/**
* list of paths to extra bootstrap jars supplied on command line
*/
Expand All @@ -340,14 +345,21 @@ public static void agentmain(String args, Instrumentation inst) throws Exception
* list of scripts read from script files
*/
private static List<String> scripts = new ArrayList<String>();

/**
* The hostname to bind the listener to, supplied on the command line (optional argument)
*/
private static String hostname = null;

/**
* The port that the listener will listen to, supplied on the command line (optional argument)
*/
private static Integer port = null;

/**
* The name of the manager class responsible for loading/unloading scripts, supplied on the
* command line (optional argument)
*/
private static String managerClassName = null;

}
25 changes: 12 additions & 13 deletions agent/src/main/java/org/jboss/byteman/agent/Retransformer.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,14 @@
*/
package org.jboss.byteman.agent;

import java.io.PrintWriter;
import java.lang.instrument.Instrumentation;
import java.util.*;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.jar.JarFile;
import java.io.PrintWriter;

/**
* byte code transformer used to introduce byteman events into JBoss code
Expand Down Expand Up @@ -146,7 +150,7 @@ public void installScript(List<String> scriptTexts, List<String> scriptNames, Pr
}
}
}

// now we can safely purge keys for all deleted scripts

for (RuleScript ruleScript : toBeRemoved) {
Expand Down Expand Up @@ -203,11 +207,6 @@ protected void listScripts(PrintWriter out) throws Exception
}
}

public void addTransformListener(String hostname, Integer port)
{
TransformListener.initialize(this, hostname, port);
}

public void removeScripts(List<String> scriptTexts, PrintWriter out) throws Exception
{
List<RuleScript> toBeRemoved;
Expand Down Expand Up @@ -243,7 +242,7 @@ public void removeScripts(List<String> scriptTexts, PrintWriter out) throws Exce
out.println("ERROR No rule scripts to remove");
return;
}

for (RuleScript ruleScript : toBeRemoved) {
if (scriptRepository.removeScript(ruleScript) != ruleScript) {
out.println("ERROR remove failed to find script " + ruleScript.getName());
Expand Down Expand Up @@ -328,10 +327,10 @@ public void appendJarFile(PrintWriter out, JarFile jarfile, boolean isBoot) thro
/**
* Returns jars that this retransformer was asked to
* {@link #appendJarFile(PrintWriter, JarFile, boolean) add} to the boot classloader.
*
*
* Note that the returned set will not include those jars that were added to the
* instrumentor object at startup via the -javaagent command line argument.
*
*
* @return set of jar pathnames for all jars loaded in the boot classloader
*/
public Set<String> getLoadedBootJars() {
Expand All @@ -341,10 +340,10 @@ public Set<String> getLoadedBootJars() {
/**
* Returns jars that this retransformer was asked to
* {@link #appendJarFile(PrintWriter, JarFile, boolean) add} to the system classloader.
*
*
* Note that the returned set will not include those jars that were added to the
* instrumentor object at startup via the -javaagent command line argument.
*
*
* @return set of jar pathnames for all jars loaded in the system classloader
*/
public Set<String> getLoadedSystemJars() {
Expand Down
38 changes: 25 additions & 13 deletions agent/src/main/java/org/jboss/byteman/agent/TransformListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,26 @@
*/
package org.jboss.byteman.agent;

import org.jboss.byteman.agent.Retransformer;
import org.jboss.byteman.rule.Rule;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.InetSocketAddress;
import java.io.*;
import java.util.List;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.jar.JarFile;

import org.jboss.byteman.rule.Rule;

/**
* a socket based listener class which reads scripts from stdin and installs them in the current runtime
*/
Expand All @@ -52,7 +58,12 @@ public class TransformListener extends Thread
private TransformListener(Retransformer retransformer)
{
this.retransformer = retransformer;
setDaemon(true);
setDaemon(true);
}

public static synchronized boolean initialize(Retransformer retransformer)
{
return (initialize(retransformer, null, null));
}

public static synchronized boolean initialize(Retransformer retransformer, String hostname, Integer port)
Expand Down Expand Up @@ -118,10 +129,11 @@ public static synchronized boolean terminate()
}
}

@Override
public void run()
{
// we don't want to see any triggers in the listener thread

Rule.disableTriggersInternal();

while (true) {
Expand Down Expand Up @@ -387,7 +399,7 @@ private void listSystemProperties(BufferedReader in, PrintWriter out) throws Exc
if (Boolean.parseBoolean(sysProps.getProperty(Transformer.SYSPROPS_STRICT_MODE, "true"))) {
strictMode = true;
}

for (Map.Entry<Object, Object> entry : sysProps.entrySet()) {
String name = entry.getKey().toString();
if (!strictMode || name.startsWith("org.jboss.byteman.")) {
Expand All @@ -398,14 +410,14 @@ private void listSystemProperties(BufferedReader in, PrintWriter out) throws Exc
out.println("OK");
out.flush();
}

private void setSystemProperties(BufferedReader in, PrintWriter out) throws Exception
{
boolean strictMode = false;
if (Boolean.parseBoolean(System.getProperty(Transformer.SYSPROPS_STRICT_MODE, "true"))) {
strictMode = true;
}

final String endMarker = "ENDSETSYSPROPS";
String line = in.readLine().trim();
while (line != null && !line.equals(endMarker)) {
Expand All @@ -417,7 +429,7 @@ private void setSystemProperties(BufferedReader in, PrintWriter out) throws Exce
String name = nameValuePair[0];
String value = nameValuePair[1];
if (strictMode && !name.startsWith("org.jboss.byteman.")) {
throw new Exception("strict mode is enabled, cannot set non-byteman system property");
throw new Exception("strict mode is enabled, cannot set non-byteman system property");
}
if (name.equals(Transformer.SYSPROPS_STRICT_MODE) && !value.equals("true")) {
// nice try
Expand All @@ -427,7 +439,7 @@ private void setSystemProperties(BufferedReader in, PrintWriter out) throws Exce
// everything looks good and we are allowed to set the system property now
if (value.length() > 0) {
// "some.sys.prop=" means the client wants to delete the system property
System.setProperty(name, value);
System.setProperty(name, value);
out.append("Set system property [" + name + "] to value [" + value + "]\n");
} else {
System.clearProperty(name);
Expand Down