<commit_before>/*
 * Copyright 2015 JKOOL, LLC.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jkoolcloud.tnt4j.stream.jmx;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

import javax.management.*;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import com.jkoolcloud.tnt4j.stream.jmx.core.Sampler;
import com.jkoolcloud.tnt4j.stream.jmx.factory.DefaultSamplerFactory;
import com.jkoolcloud.tnt4j.stream.jmx.factory.SamplerFactory;
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;

/**
 * <p>
 * This class provides java agent implementation {@link #premain(String, Instrumentation)},
 * {@link #agentmain(String, Instrumentation)} as well as {@link #main(String[])} entry point to run as a standalone
 * application.
 * </p>
 * 
 * @version $Revision: 1 $
 * 
 * @see SamplerFactory
 */
public class SamplingAgent {
	protected static Sampler platformJmx;
	protected static ConcurrentHashMap<MBeanServerConnection, Sampler> STREAM_AGENTS = new ConcurrentHashMap<MBeanServerConnection, Sampler>(89);
	protected static boolean TRACE = Boolean.getBoolean("com.jkoolcloud.tnt4j.stream.jmx.agent.trace");
	protected static boolean VALIDATE_TYPES = Boolean.getBoolean("com.jkoolcloud.tnt4j.stream.jmx.agent.validate.types");

	/**
	 * Entry point to be loaded as {@code -javaagent:jarpath="mbean-filter!sample.ms"} command line.
	 * Example:  {@code -javaagent:tnt4j-sample-jmx.jar="*:*!30000"}
	 * 
	 * @param options '!' separated list of options mbean-filter!sample.ms, where mbean-filter is semicolon separated list of mbean filters
	 * @param inst instrumentation handle
	 */
	public static void premain(String options, Instrumentation inst) throws IOException {
		String incFilter = System.getProperty("com.jkoolcloud.tnt4j.stream.jmx.include.filter", Sampler.JMX_FILTER_ALL);
		String excFilter = System.getProperty("com.jkoolcloud.tnt4j.stream.jmx.exclude.filter", Sampler.JMX_FILTER_NONE);
		int period = Integer.getInteger("com.jkoolcloud.tnt4j.stream.jmx.period", 30000);
		if (options != null) {
			String[] args = options.split("!");
			if (args.length >= 2) {
				incFilter = args[0];
				period = Integer.parseInt(args[1]);
			}
		}
		sample(incFilter, excFilter, period, TimeUnit.MILLISECONDS);
		System.out.println("SamplingAgent.premain: inlcude.filter=" + incFilter 
				+ ", exclude.filter=" + excFilter
				+ ", sample.ms=" + period 
				+ ", trace=" + TRACE 
				+ ", validate.types=" + VALIDATE_TYPES
				+ ", tnt4j.config=" + System.getProperty("tnt4j.config") 
				+ ", jmx.sample.list=" + STREAM_AGENTS);
	}

	/**
	 * Entry point to bea loaded as JVM agent. Does same as {@link #premain(String, Instrumentation)}.
	 * 
	 * @param agentArgs '!' separated list of options mbean-filter!sample.ms, where mbean-filter is semicolon separated list of mbean filters
	 * @param inst instrumentation handle
	 * @throws IOException if any I/O exception occurs while starting agent
	 *
	 * @see #premain(String, Instrumentation)
	 */
	public static void agentmain(String agentArgs, Instrumentation inst) throws Exception {
		String agentParams = "";
		String tnt4jProp = System.getProperty("tnt4j.config");
		String agentLibPath = "";
		if (!isEmpty(agentArgs)) {
			String[] args = agentArgs.split("!");

			if (args.length >= 2) {
				agentParams = args[0] + "!" + args[1];
			}

			for (String arg : args) {
				if (arg.startsWith("-Dtnt4j.config")) {
					if (isEmpty(tnt4jProp)) {
						String[] prop = arg.split("=");
						tnt4jProp = prop.length > 1 ? prop[1] : null;

						System.setProperty("tnt4j.config", tnt4jProp);
					}
				} else if (arg.startsWith("-DSamplingAgent.path")) {
					String[] prop = arg.split("=");
					agentLibPath = prop.length > 1 ? prop[1] : null;
				} else if (arg.startsWith("trace=")) {
					String[] prop = arg.split("=");
					TRACE = prop.length > 1 ? Boolean.parseBoolean(prop[1]) : TRACE;
				} else if (arg.startsWith("validate=")) {
					String[] prop = arg.split("=");
					VALIDATE_TYPES = prop.length > 1 ? Boolean.parseBoolean(prop[1]) : VALIDATE_TYPES;
				}
			}
		}

		System.out.println("SamplingAgent.agentmain: agent.params=" + agentParams 
				+ ", agent.lib.path=" + agentLibPath
				+ ", trace=" + TRACE 
				+ ", validate.types=" + VALIDATE_TYPES 
				+ ", tnt4j.config=" + System.getProperty("tnt4j.config"));

		File agentPath = new File(agentLibPath);
		final String[] classPathEntries = agentPath.list(new JarFilter());
		if (classPathEntries != null) {
			File pathFile;
			for (String classPathEntry : classPathEntries) {
				pathFile = new File(classPathEntry);
				extendClasspath(pathFile.toURI().toURL());
			}
		}

		premain(agentParams, inst);
	}

	/**
	 * Loads required classpath entries to running JVM.
	 *
	 * @param classPathEntriesURL classpath entries URLs to attach to JVM
	 * @throws Exception if exception occurs while extending system class loader's classpath
	 */
	private static void extendClasspath(URL... classPathEntriesURL) throws Exception {
		URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
		Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
		method.setAccessible(true);
		for (URL classPathEntryURL : classPathEntriesURL) {
			try {
				method.invoke(classLoader, classPathEntryURL);
			} catch (Exception e) {
				System.err.println("SamplingAgent.extendClasspath: Could not load lib " + classPathEntryURL);
				System.err.println("                    Exception: " + e.getLocalizedMessage());
				// e.printStackTrace ();
			}
		}
	}

	/**
	 * Main entry point for running as a standalone application (test only).
	 * 
	 * @param args
	 *            argument list: mbean-filter sample_time_ms
	 */
	public static void main(String[] args) throws Exception {
		if (args.length < 2) {
			System.out.println("Usage: mbean-filter exclude-filter sample-ms [wait-ms] (e.g \"*:*\" \"\" 10000 60000)");
			System.out.println("   or: -attach vmName/vmId agentJarPath (e.g -attach activemq [ENV_PATH]/tnt-stream-jmx.jar)");
			System.out.println("   or: -connect vmName/vmId (e.g -connect activemq");
		}
		if (args[0].equalsIgnoreCase("-connect")) {
			String vmDescr = args[1];
			String agentOptions = args.length > 2 ? args[2] : "*:*!10000";

			connect(vmDescr, agentOptions);
		} else if (args[0].equalsIgnoreCase("-attach")) {
			String vmDescr = args[1];
			String jarPath = args[2];
			String agentOptions = args.length > 3 ? args[3] : "*:*!10000";

			attach(vmDescr, jarPath, agentOptions);
		} else {
			try {
				long sample_time = Integer.parseInt(args[2]);
				long wait_time = args.length > 3 ? Integer.parseInt(args[3]) : 0;
				sample(args[0], args[1], sample_time, TimeUnit.MILLISECONDS);
				System.out.println("SamplingAgent.main: inlcude.filter=" + args[0] 
						+ ", exclude.filter=" + args[1]
						+ ", sample.ms=" + sample_time 
						+ ", wait.ms=" + wait_time 
						+ ", trace=" + TRACE
						+ ", validate.types=" + VALIDATE_TYPES 
						+ ", tnt4j.config=" + System.getProperty("tnt4j.config")
						+ ", jmx.sample.list=" + STREAM_AGENTS);<commit_msg>Now can connect to any JMX service providing service URL as JVM descriptor.<commit_after>/*
 * Copyright 2015 JKOOL, LLC.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jkoolcloud.tnt4j.stream.jmx;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

import javax.management.*;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import com.jkoolcloud.tnt4j.stream.jmx.core.Sampler;
import com.jkoolcloud.tnt4j.stream.jmx.factory.DefaultSamplerFactory;
import com.jkoolcloud.tnt4j.stream.jmx.factory.SamplerFactory;
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;

/**
 * <p>
 * This class provides java agent implementation {@link #premain(String, Instrumentation)},
 * {@link #agentmain(String, Instrumentation)} as well as {@link #main(String[])} entry point to run as a standalone
 * application.
 * </p>
 * 
 * @version $Revision: 1 $
 * 
 * @see SamplerFactory
 */
public class SamplingAgent {
	protected static Sampler platformJmx;
	protected static ConcurrentHashMap<MBeanServerConnection, Sampler> STREAM_AGENTS = new ConcurrentHashMap<MBeanServerConnection, Sampler>(89);
	protected static boolean TRACE = Boolean.getBoolean("com.jkoolcloud.tnt4j.stream.jmx.agent.trace");
	protected static boolean VALIDATE_TYPES = Boolean.getBoolean("com.jkoolcloud.tnt4j.stream.jmx.agent.validate.types");

	/**
	 * Entry point to be loaded as {@code -javaagent:jarpath="mbean-filter!sample.ms"} command line.
	 * Example:  {@code -javaagent:tnt4j-sample-jmx.jar="*:*!30000"}
	 * 
	 * @param options '!' separated list of options mbean-filter!sample.ms, where mbean-filter is semicolon separated list of mbean filters
	 * @param inst instrumentation handle
	 */
	public static void premain(String options, Instrumentation inst) throws IOException {
		String incFilter = System.getProperty("com.jkoolcloud.tnt4j.stream.jmx.include.filter", Sampler.JMX_FILTER_ALL);
		String excFilter = System.getProperty("com.jkoolcloud.tnt4j.stream.jmx.exclude.filter", Sampler.JMX_FILTER_NONE);
		int period = Integer.getInteger("com.jkoolcloud.tnt4j.stream.jmx.period", 30000);
		if (options != null) {
			String[] args = options.split("!");
			if (args.length >= 2) {
				incFilter = args[0];
				period = Integer.parseInt(args[1]);
			}
		}
		sample(incFilter, excFilter, period, TimeUnit.MILLISECONDS);
		System.out.println("SamplingAgent.premain: inlcude.filter=" + incFilter 
				+ ", exclude.filter=" + excFilter
				+ ", sample.ms=" + period 
				+ ", trace=" + TRACE 
				+ ", validate.types=" + VALIDATE_TYPES
				+ ", tnt4j.config=" + System.getProperty("tnt4j.config") 
				+ ", jmx.sample.list=" + STREAM_AGENTS);
	}

	/**
	 * Entry point to bea loaded as JVM agent. Does same as {@link #premain(String, Instrumentation)}.
	 * 
	 * @param agentArgs '!' separated list of options mbean-filter!sample.ms, where mbean-filter is semicolon separated list of mbean filters
	 * @param inst instrumentation handle
	 * @throws IOException if any I/O exception occurs while starting agent
	 *
	 * @see #premain(String, Instrumentation)
	 */
	public static void agentmain(String agentArgs, Instrumentation inst) throws Exception {
		String agentParams = "";
		String tnt4jProp = System.getProperty("tnt4j.config");
		String agentLibPath = "";
		if (!isEmpty(agentArgs)) {
			String[] args = agentArgs.split("!");

			if (args.length >= 2) {
				agentParams = args[0] + "!" + args[1];
			}

			for (String arg : args) {
				if (arg.startsWith("-Dtnt4j.config")) {
					if (isEmpty(tnt4jProp)) {
						String[] prop = arg.split("=");
						tnt4jProp = prop.length > 1 ? prop[1] : null;

						System.setProperty("tnt4j.config", tnt4jProp);
					}
				} else if (arg.startsWith("-DSamplingAgent.path")) {
					String[] prop = arg.split("=");
					agentLibPath = prop.length > 1 ? prop[1] : null;
				} else if (arg.startsWith("trace=")) {
					String[] prop = arg.split("=");
					TRACE = prop.length > 1 ? Boolean.parseBoolean(prop[1]) : TRACE;
				} else if (arg.startsWith("validate=")) {
					String[] prop = arg.split("=");
					VALIDATE_TYPES = prop.length > 1 ? Boolean.parseBoolean(prop[1]) : VALIDATE_TYPES;
				}
			}
		}

		System.out.println("SamplingAgent.agentmain: agent.params=" + agentParams 
				+ ", agent.lib.path=" + agentLibPath
				+ ", trace=" + TRACE 
				+ ", validate.types=" + VALIDATE_TYPES 
				+ ", tnt4j.config=" + System.getProperty("tnt4j.config"));

		File agentPath = new File(agentLibPath);
		final String[] classPathEntries = agentPath.list(new JarFilter());
		if (classPathEntries != null) {
			File pathFile;
			for (String classPathEntry : classPathEntries) {
				pathFile = new File(classPathEntry);
				extendClasspath(pathFile.toURI().toURL());
			}
		}

		premain(agentParams, inst);
	}

	/**
	 * Loads required classpath entries to running JVM.
	 *
	 * @param classPathEntriesURL classpath entries URLs to attach to JVM
	 * @throws Exception if exception occurs while extending system class loader's classpath
	 */
	private static void extendClasspath(URL... classPathEntriesURL) throws Exception {
		URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
		Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
		method.setAccessible(true);
		for (URL classPathEntryURL : classPathEntriesURL) {
			try {
				method.invoke(classLoader, classPathEntryURL);
			} catch (Exception e) {
				System.err.println("SamplingAgent.extendClasspath: Could not load lib " + classPathEntryURL);
				System.err.println("                    Exception: " + e.getLocalizedMessage());
				// e.printStackTrace ();
			}
		}
	}

	/**
	 * Main entry point for running as a standalone application (test only).
	 * 
	 * @param args
	 *            argument list: mbean-filter sample_time_ms
	 */
	public static void main(String[] args) throws Exception {
		if (args.length < 2) {
			System.out.println("Usage: mbean-filter exclude-filter sample-ms [wait-ms] (e.g \"*:*\" \"\" 10000 60000)");
			System.out.println("   or: -attach vmName/vmId agentJarPath (e.g -attach activemq [ENV_PATH]/tnt-stream-jmx.jar)");
			System.out.println("   or: -connect vmName/vmId/JMX_URL (e.g -connect activemq");
		}
		if (args[0].equalsIgnoreCase("-connect")) {
			String vmDescr = args[1];
			String agentOptions = args.length > 2 ? args[2] : "*:*!10000";

			connect(vmDescr, agentOptions);
		} else if (args[0].equalsIgnoreCase("-attach")) {
			String vmDescr = args[1];
			String jarPath = args[2];
			String agentOptions = args.length > 3 ? args[3] : "*:*!10000";

			attach(vmDescr, jarPath, agentOptions);
		} else {
			try {
				long sample_time = Integer.parseInt(args[2]);
				long wait_time = args.length > 3 ? Integer.parseInt(args[3]) : 0;
				sample(args[0], args[1], sample_time, TimeUnit.MILLISECONDS);
				System.out.println("SamplingAgent.main: inlcude.filter=" + args[0] 
						+ ", exclude.filter=" + args[1]
						+ ", sample.ms=" + sample_time 
						+ ", wait.ms=" + wait_time 
						+ ", trace=" + TRACE
						+ ", validate.types=" + VALIDATE_TYPES 
						+ ", tnt4j.config=" + System.getProperty("tnt4j.config")
						+ ", jmx.sample.list=" + STREAM_AGENTS);
{'fraction_non_alphanumeric': 0.13546214294623923, 'fraction_numerical': 0.011974554072595733, 'mean_word_length': 3.96901146575767, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6720082', 'n_tokens_mistral': 5688, 'n_tokens_neox': 5051, 'n_words': 1217}