All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.grinder.engine.process.dcr.DCRContextImplementation Maven / Gradle / Ivy

The newest version!
// Copyright (C) 2009 - 2011 Philip Aston
// All rights reserved.
//
// This file is part of The Grinder software distribution. Refer to
// the file LICENSE which is part of The Grinder distribution for
// licensing details. The Grinder distribution is available on the
// Internet at http://grinder.sourceforge.net/
//
// 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 HOLDERS 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 net.grinder.engine.process.dcr;

import java.lang.instrument.Instrumentation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

import org.slf4j.Logger;

import net.grinder.script.NonInstrumentableTypeException;
import net.grinder.scriptengine.DCRContext;
import net.grinder.scriptengine.Recorder;
import net.grinder.util.weave.Weaver;
import net.grinder.util.weave.WeavingException;
import net.grinder.util.weave.Weaver.TargetSource;
import net.grinder.util.weave.agent.ExposeInstrumentation;
import net.grinder.util.weave.j2se6.ASMTransformerFactory;
import net.grinder.util.weave.j2se6.DCRWeaver;

/**
 * Wrap up the DCR context for use by
 * {@link net.grinder.scriptengine.AbstractDCRInstrumenter}
 * implementations.
 *
 * @author Philip Aston
 */
public final class DCRContextImplementation implements DCRContext {

  private static final String[] NON_INSTRUMENTABLE_PACKAGES = {
    "net.grinder.engine.process",
    "extra166y",
    "org.objectweb.asm",
  };

  private static final ClassLoader BOOTSTRAP_CLASSLOADER =
    Object.class.getClassLoader();

  private final Weaver m_weaver;
  private final RecorderRegistry m_recorderRegistry;

  /**
   * Attempt to create a context.
   *
   * @param logger A logger to complain to if problems are found.
   * @return The context, or {@code null} if one could not be created.
   */
  public static DCRContextImplementation create(Logger logger) {
    final Instrumentation instrumentation =
      ExposeInstrumentation.getInstrumentation();

    try {
      final Method m =
        Instrumentation.class.getMethod("isRetransformClassesSupported");

      if (!(Boolean)m.invoke(instrumentation)) {
        logger.info(
          "Java VM does not support class retransformation, DCR unavailable");

        return null;
      }
    }
    catch (Exception e1) {
      // Also catches case where instrumentation == null.
      logger.info("Java VM does not support instrumentation, DCR unavailable");

      return null;
    }

    return new DCRContextImplementation(instrumentation,
                                        RecorderLocator.class,
                                        RecorderLocator.getRecorderRegistry());
  }

  /**
   * Constructor.
   *
   * 

Package scope for unit tests.

*/ DCRContextImplementation(Instrumentation instrumentation, Class recorderLocatorClass, RecorderRegistry recorderRegistry) { final ASMTransformerFactory transformerFactory; try { transformerFactory = new ASMTransformerFactory(recorderLocatorClass); } catch (WeavingException e) { throw new AssertionError(e); } m_weaver = new DCRWeaver(transformerFactory, instrumentation); m_recorderRegistry = recorderRegistry; } /** * {@inheritDoc} */ @Override public void add(Object target, Constructor constructor, Recorder recorder) throws NonInstrumentableTypeException { checkWrappable(constructor.getDeclaringClass()); final String location = m_weaver.weave(constructor); // System.out.printf("add(%s, %s, %s, %s)%n", // target.hashCode(), location, // target, // constructor); m_recorderRegistry.register(target, location, recorder); } /** * {@inheritDoc} */ @Override public void add(Object target, Method method, TargetSource targetSource, Recorder recorder) throws NonInstrumentableTypeException { checkWrappable(method.getDeclaringClass()); try { final String location = m_weaver.weave(method, targetSource); m_recorderRegistry.register(target, location, recorder); } catch (WeavingException e) { throw new NonInstrumentableTypeException("Weaving failed", e); } // System.out.printf("add(%s, %s, %s, %s)%n", // target.hashCode(), location, // target, // method); } private void checkWrappable(Class theClass) throws NonInstrumentableTypeException { final String whyNot = whyCantIInstrument(theClass); if (whyNot != null) { throw new NonInstrumentableTypeException( "Cannot instrument " + theClass + " because " + whyNot); } } private String whyCantIInstrument(Class targetClass) { // We disallow instrumentation of these classes to avoid the need for // complex protection against recursion in the engine itself. // Also, classes from the bootstrap classloader can't statically // refer to RecorderLocator. if (targetClass.getClassLoader() == BOOTSTRAP_CLASSLOADER) { return "it belongs to the bootstrap classloader"; } // Hack to allow the classic hello world examples work. // See bug 3411728. if ("net.grinder.engine.process.ExternalLogger".equals( targetClass.getName())) { return null; } final Package thePackage = targetClass.getPackage(); if (thePackage != null) { final String packageName = thePackage.getName(); for (String prefix : NON_INSTRUMENTABLE_PACKAGES) { if (packageName.startsWith(prefix)) { return "it belongs to the " + prefix + " package"; } } } return null; } /** * {@inheritDoc} */ @Override public boolean isInstrumentable(Class targetClass) { return whyCantIInstrument(targetClass) == null; } /** * {@inheritDoc} */ @Override public void applyChanges() throws WeavingException { m_weaver.applyChanges(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy