<commit_before>/*
 * Copyright 2010-2012 VMware and contributors
 *
 * 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 org.springsource.loaded.agent;

import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URI;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.springsource.loaded.Constants;
import org.springsource.loaded.GlobalConfiguration;
import org.springsource.loaded.IsReloadableTypePlugin;
import org.springsource.loaded.LoadtimeInstrumentationPlugin;
import org.springsource.loaded.Log;
import org.springsource.loaded.Plugin;
import org.springsource.loaded.ReloadableType;
import org.springsource.loaded.SystemClassReflectionInvestigator;
import org.springsource.loaded.SystemClassReflectionRewriter;
import org.springsource.loaded.SystemClassReflectionRewriter.RewriteResult;
import org.springsource.loaded.TypeRegistry;
import org.springsource.loaded.TypeRegistry.ReloadableTypeNameDecision;
import org.springsource.loaded.Utils;
import org.springsource.loaded.ri.ReflectiveInterceptor;
import org.springsource.loaded.support.Java8;

/**
 * The entry point for the agent - all classes that can be modified will be passed into preProcess(). They have to be
 * dealt with in one of these ways:
 * <ul>
 * <li>reloadable types need their bytecode rewriting so that they can be modified later
 * <li>'framework' types (not loaded by the system classloader) need their reflection calls rewritten
 * <li>system classes also need their reflection calls modified but in a different way (they cannot have dependencies on
 * types they cannot see)
 * </ul>
 *
 * @author <NAME>
 * @since 0.5.0
 */
public class SpringLoadedPreProcessor implements Constants {

	private static Logger log = Logger.getLogger(SpringLoadedPreProcessor.class.getName());

	private static List<Plugin> plugins = null;

	// Global control to turn off the agent, used when testing
	public static boolean disabled = false;

	// These are system classes that contain reflection code and so need instrumenting when encountered.
	private static List<String> systemClassesContainingReflection;

	// Once the system classes have been encountered and instrumented, they need initialization once they have been defined
	// to the VM.  This records the list of those that have not yet been initialized.
	private Map<String, Integer> systemClassesRequiringInitialization = new HashMap<String, Integer>();

	// Once the first reloadabletype is hit, we can start initializing the system classes with reflective interceptors.
	// Doing it early can lead to hangs
	private static boolean firstReloadableTypeHit = false;

	public void initialize() {
		// When spring loaded is running as an agent, it should not be defining types directly (this setting does not apply to
		// the generated suuport types)
		GlobalConfiguration.directlyDefineTypes = false;
		GlobalConfiguration.fileSystemMonitoring = true;
		systemClassesContainingReflection = new ArrayList<String>();
		// So that jaxb annotations will cause discovery of the correct properties:
		systemClassesContainingReflection.add("com/sun/xml/internal/bind/v2/model/nav/ReflectionNavigator");
		// So that proxies are generated with the right set of methods inside
		systemClassesContainingReflection.add("sun/misc/ProxyGenerator");
		// (at least) the call to getModifiers() needs interception
		systemClassesContainingReflection.add("java/lang/reflect/Proxy");
		// So that javabeans introspection is intercepter
		systemClassesContainingReflection.add("java/beans/Introspector");

		// Related to serialization
		// TODO [serialization] Caches in ObjectStreamClass for descriptors, need clearing on reload
		systemClassesContainingReflection.add("java/io/ObjectStreamClass");
		systemClassesContainingReflection.add("java/io/ObjectStreamClass$EntryFuture");

		// Don't need this right now, instead we are not removing 'final' from the serialVersionUID
		//		// Need to catch at least the call to access the serialVersionUID made in getDeclaredSUID()
		//		systemClassesContainingReflection.add("java/io/ObjectStreamClass$2");
	}

	/**
	 * Main entry point to Spring Loaded when it is running as an agent. This method will use the classLoader and the
	 * class name in order to determine whether the type should be made reloadable. Non-reloadable types will at least
	 * get their call sites rewritten.
	 *
	 * @param classLoader the classloader loading this type
	 * @param slashedClassName the slashed class name (e.g. java/lang/String) being loaded
	 * @param protectionDomain the protection domain for the loaded class
	 * @param bytes the class bytes for the class being loaded
	 * @return potentially modified bytes
	 */
	public byte[] preProcess(ClassLoader classLoader, String slashedClassName, ProtectionDomain protectionDomain,
			byte[] bytes) {
		if (disabled) {
			return bytes;
		}

		if (slashedClassName == null && bytes != null) {
			// The lambda meta factory can spin up classes that come through here with no class name specified
			//			slashedClassName = Utils.discoverClassname(bytes);
		}

		// TODO need configurable debug here, ability to dump any code before/after
		for (Plugin plugin : getGlobalPlugins()) {
			if (plugin instanceof LoadtimeInstrumentationPlugin) {
				LoadtimeInstrumentationPlugin loadtimeInstrumentationPlugin = (LoadtimeInstrumentationPlugin) plugin;
				if (loadtimeInstrumentationPlugin.accept(slashedClassName, classLoader, protectionDomain, bytes)) {
					bytes = loadtimeInstrumentationPlugin.modify(slashedClassName, classLoader, bytes);
				}<commit_msg>uncomment line<commit_after>/*
 * Copyright 2010-2012 VMware and contributors
 *
 * 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 org.springsource.loaded.agent;

import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URI;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.springsource.loaded.Constants;
import org.springsource.loaded.GlobalConfiguration;
import org.springsource.loaded.IsReloadableTypePlugin;
import org.springsource.loaded.LoadtimeInstrumentationPlugin;
import org.springsource.loaded.Log;
import org.springsource.loaded.Plugin;
import org.springsource.loaded.ReloadableType;
import org.springsource.loaded.SystemClassReflectionInvestigator;
import org.springsource.loaded.SystemClassReflectionRewriter;
import org.springsource.loaded.SystemClassReflectionRewriter.RewriteResult;
import org.springsource.loaded.TypeRegistry;
import org.springsource.loaded.TypeRegistry.ReloadableTypeNameDecision;
import org.springsource.loaded.Utils;
import org.springsource.loaded.ri.ReflectiveInterceptor;
import org.springsource.loaded.support.Java8;

/**
 * The entry point for the agent - all classes that can be modified will be passed into preProcess(). They have to be
 * dealt with in one of these ways:
 * <ul>
 * <li>reloadable types need their bytecode rewriting so that they can be modified later
 * <li>'framework' types (not loaded by the system classloader) need their reflection calls rewritten
 * <li>system classes also need their reflection calls modified but in a different way (they cannot have dependencies on
 * types they cannot see)
 * </ul>
 *
 * @author <NAME>
 * @since 0.5.0
 */
public class SpringLoadedPreProcessor implements Constants {

	private static Logger log = Logger.getLogger(SpringLoadedPreProcessor.class.getName());

	private static List<Plugin> plugins = null;

	// Global control to turn off the agent, used when testing
	public static boolean disabled = false;

	// These are system classes that contain reflection code and so need instrumenting when encountered.
	private static List<String> systemClassesContainingReflection;

	// Once the system classes have been encountered and instrumented, they need initialization once they have been defined
	// to the VM.  This records the list of those that have not yet been initialized.
	private Map<String, Integer> systemClassesRequiringInitialization = new HashMap<String, Integer>();

	// Once the first reloadabletype is hit, we can start initializing the system classes with reflective interceptors.
	// Doing it early can lead to hangs
	private static boolean firstReloadableTypeHit = false;

	public void initialize() {
		// When spring loaded is running as an agent, it should not be defining types directly (this setting does not apply to
		// the generated suuport types)
		GlobalConfiguration.directlyDefineTypes = false;
		GlobalConfiguration.fileSystemMonitoring = true;
		systemClassesContainingReflection = new ArrayList<String>();
		// So that jaxb annotations will cause discovery of the correct properties:
		systemClassesContainingReflection.add("com/sun/xml/internal/bind/v2/model/nav/ReflectionNavigator");
		// So that proxies are generated with the right set of methods inside
		systemClassesContainingReflection.add("sun/misc/ProxyGenerator");
		// (at least) the call to getModifiers() needs interception
		systemClassesContainingReflection.add("java/lang/reflect/Proxy");
		// So that javabeans introspection is intercepter
		systemClassesContainingReflection.add("java/beans/Introspector");

		// Related to serialization
		// TODO [serialization] Caches in ObjectStreamClass for descriptors, need clearing on reload
		systemClassesContainingReflection.add("java/io/ObjectStreamClass");
		systemClassesContainingReflection.add("java/io/ObjectStreamClass$EntryFuture");

		// Don't need this right now, instead we are not removing 'final' from the serialVersionUID
		//		// Need to catch at least the call to access the serialVersionUID made in getDeclaredSUID()
		//		systemClassesContainingReflection.add("java/io/ObjectStreamClass$2");
	}

	/**
	 * Main entry point to Spring Loaded when it is running as an agent. This method will use the classLoader and the
	 * class name in order to determine whether the type should be made reloadable. Non-reloadable types will at least
	 * get their call sites rewritten.
	 *
	 * @param classLoader the classloader loading this type
	 * @param slashedClassName the slashed class name (e.g. java/lang/String) being loaded
	 * @param protectionDomain the protection domain for the loaded class
	 * @param bytes the class bytes for the class being loaded
	 * @return potentially modified bytes
	 */
	public byte[] preProcess(ClassLoader classLoader, String slashedClassName, ProtectionDomain protectionDomain,
			byte[] bytes) {
		if (disabled) {
			return bytes;
		}

		if (slashedClassName == null && bytes != null) {
			// The lambda meta factory can spin up classes that come through here with no class name specified
			slashedClassName = Utils.discoverClassname(bytes);
		}

		// TODO need configurable debug here, ability to dump any code before/after
		for (Plugin plugin : getGlobalPlugins()) {
			if (plugin instanceof LoadtimeInstrumentationPlugin) {
				LoadtimeInstrumentationPlugin loadtimeInstrumentationPlugin = (LoadtimeInstrumentationPlugin) plugin;
				if (loadtimeInstrumentationPlugin.accept(slashedClassName, classLoader, protectionDomain, bytes)) {
					bytes = loadtimeInstrumentationPlugin.modify(slashedClassName, classLoader, bytes);
				}
{'fraction_non_alphanumeric': 0.07414987405541562, 'fraction_numerical': 0.0028337531486146094, 'mean_word_length': 4.928604759682687, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 2}, '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': '2281336', 'n_tokens_mistral': 3393, 'n_tokens_neox': 3222, 'n_words': 1237}