/**
  * Performs a benchmark of an interface implementation using cglib.
  *
  * @return The created instance, in order to avoid JIT removal.
  */
 @Benchmark
 public ExampleInterface benchmarkCglib() {
   Enhancer enhancer = new Enhancer();
   enhancer.setUseCache(false);
   enhancer.setClassLoader(newClassLoader());
   enhancer.setSuperclass(baseClass);
   CallbackHelper callbackHelper =
       new CallbackHelper(Object.class, new Class[] {baseClass}) {
         @Override
         protected Object getCallback(Method method) {
           if (method.getDeclaringClass() == baseClass) {
             return new FixedValue() {
               @Override
               public Object loadObject() throws Exception {
                 return null;
               }
             };
           } else {
             return NoOp.INSTANCE;
           }
         }
       };
   enhancer.setCallbackFilter(callbackHelper);
   enhancer.setCallbacks(callbackHelper.getCallbacks());
   return (ExampleInterface) enhancer.create();
 }
 @SuppressWarnings("unchecked")
 public List<Class<? extends ModuleProvider<?>>> getModuleClasses() {
   List<Class<? extends ModuleProvider<?>>> out =
       new ArrayList<Class<? extends ModuleProvider<?>>>();
   for (int i = 0; i < 10; i++) {
     Enhancer enhancer = new Enhancer();
     enhancer.setSuperclass(NullModule.class);
     enhancer.setClassLoader(this.getClass().getClassLoader());
     enhancer.setCallbackTypes(new Class[] {Callback1.class});
     enhancer.setSerialVersionUID(new Long(i));
     enhancer.setInterfaces(new Class[] {Module.class});
     out.add(enhancer.createClass());
   }
   return out;
 }
Beispiel #3
0
  @Override
  public <T extends PropertyContainer> Object createProxy(
      T container, TypeWrapper<T> wrapper, Class<?> instanceClass) {

    CglibEntityInterceptor<T> interceptor = new CglibEntityInterceptor<T>(container, wrapper);

    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(instanceClass);
    enhancer.setInterfaces(new Class[] {ContainerWrapper.class});
    enhancer.setCallback(interceptor);
    enhancer.setClassLoader(config.getResourceLoader().getClassLoader());

    Object proxy = enhancer.create();

    wrapper.onLoad(proxy, container);

    return proxy;
  }
  private Object createServiceInterfaceProxy(
      String serviceInterfaceClassName,
      Map seiPortNameToFactoryMap,
      Map seiClassNameToFactoryMap,
      ClassLoader classLoader)
      throws NamingException {
    boolean initialize = (this.serviceConstructor == null);

    if (initialize) {
      Class serviceInterface;
      try {
        serviceInterface = classLoader.loadClass(serviceInterfaceClassName);
      } catch (ClassNotFoundException e) {
        throw (NamingException)
            new NamingException(
                    "Could not load service interface class " + serviceInterfaceClassName)
                .initCause(e);
      }

      // create method interceptors
      Callback callback = new ServiceMethodInterceptor(seiPortNameToFactoryMap);
      this.methodInterceptors = new Callback[] {NoOp.INSTANCE, callback};

      // create service class
      Enhancer enhancer = new Enhancer();
      enhancer.setClassLoader(classLoader);
      enhancer.setSuperclass(ServiceImpl.class);
      enhancer.setInterfaces(new Class[] {serviceInterface});
      enhancer.setCallbackFilter(new NoOverrideCallbackFilter(Service.class));
      enhancer.setCallbackTypes(new Class[] {NoOp.class, MethodInterceptor.class});
      enhancer.setUseFactory(false);
      enhancer.setUseCache(false);
      this.enhancedServiceClass = enhancer.createClass();

      // get constructor
      this.serviceConstructor =
          FastClass.create(this.enhancedServiceClass).getConstructor(SERVICE_CONSTRUCTOR_TYPES);
    }

    // associate the method interceptors with the generated service class on the current thread
    Enhancer.registerCallbacks(this.enhancedServiceClass, this.methodInterceptors);

    Object[] arguments = new Object[] {seiPortNameToFactoryMap, seiClassNameToFactoryMap};

    Object serviceInstance = null;

    try {
      serviceInstance = this.serviceConstructor.newInstance(arguments);
    } catch (InvocationTargetException e) {
      throw (NamingException)
          new NamingException("Could not construct service instance")
              .initCause(e.getTargetException());
    }

    if (initialize) {
      for (Iterator iterator = seiPortNameToFactoryMap.values().iterator(); iterator.hasNext(); ) {
        SeiFactoryImpl seiFactory = (SeiFactoryImpl) iterator.next();
        try {
          seiFactory.initialize(serviceInstance, classLoader);
        } catch (ClassNotFoundException e) {
          throw (NamingException)
              new NamingException("Could not load service interface class; " + e.getMessage())
                  .initCause(e);
        }
      }
    }

    return serviceInstance;
  }
  private boolean tryInjectManager() {
    Class<?> serverClass = serverHandler.getClass();

    Enhancer ex = new Enhancer();
    Callback sendPacketCallback =
        new MethodInterceptor() {
          @Override
          public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)
              throws Throwable {
            Object packet = args[0];

            if (packet != null) {
              packet = handlePacketSending(packet);

              // A NULL packet indicate cancelling
              if (packet != null) args[0] = packet;
              else return null;
            }

            // Call the method directly
            return proxy.invokeSuper(obj, args);
          };
        };
    Callback noOpCallback = NoOp.INSTANCE;

    // Share callback filter - that way, we avoid generating a new class for
    // every logged in player.
    if (callbackFilter == null) {
      callbackFilter =
          new CallbackFilter() {
            @Override
            public int accept(Method method) {
              if (method.equals(sendPacketMethod)) return 0;
              else return 1;
            }
          };
    }

    ex.setClassLoader(classLoader);
    ex.setSuperclass(serverClass);
    ex.setCallbacks(new Callback[] {sendPacketCallback, noOpCallback});
    ex.setCallbackFilter(callbackFilter);

    // Find the Minecraft NetServerHandler superclass
    Class<?> minecraftSuperClass = getFirstMinecraftSuperClass(serverHandler.getClass());
    ExistingGenerator generator =
        ExistingGenerator.fromObjectFields(serverHandler, minecraftSuperClass);
    DefaultInstances serverInstances = null;

    // Maybe the proxy instance can help?
    Object proxyInstance = getProxyServerHandler();

    // Use the existing server proxy when we create one
    if (proxyInstance != null && proxyInstance != serverHandler) {
      serverInstances =
          DefaultInstances.fromArray(
              generator, ExistingGenerator.fromObjectArray(new Object[] {proxyInstance}));
    } else {
      serverInstances = DefaultInstances.fromArray(generator);
    }

    serverInstances.setNonNull(true);
    serverInstances.setMaximumRecursion(1);

    Object proxyObject = serverInstances.forEnhancer(ex).getDefault(serverClass);

    // Inject it now
    if (proxyObject != null) {
      // This will be done by InjectedServerConnection instead
      // copyTo(serverHandler, proxyObject);

      serverInjection.replaceServerHandler(serverHandler, proxyObject);
      serverHandlerRef.setValue(proxyObject);
      return true;
    } else {
      return false;
    }
  }
  @SuppressWarnings("unchecked")
  public <T> T createProxy(
      Class<T> toMock, InvocationHandler handler, Method[] mockedMethods, ConstructorArgs args) {
    Enhancer enhancer = createEnhancer(toMock);

    MockMethodInterceptor interceptor = new MockMethodInterceptor(handler);
    if (mockedMethods != null) {
      interceptor.setMockedMethods(mockedMethods);
    }
    enhancer.setCallbackType(interceptor.getClass());

    Class<?> mockClass;
    try {
      mockClass = enhancer.createClass();
    } catch (CodeGenerationException e) {
      // ///CLOVER:OFF (don't know how to test it automatically)
      // Probably caused by a NoClassDefFoundError, to use two class loaders at the same time
      // instead of the default one (which is the class to mock one)
      // This is required by Eclipse Plug-ins, the mock class loader doesn't see
      // cglib most of the time. Using EasyMock and the mock class loader at the same time solves
      // this
      LinkedClassLoader linkedClassLoader =
          new LinkedClassLoader(toMock.getClassLoader(), ClassProxyFactory.class.getClassLoader());
      enhancer.setClassLoader(linkedClassLoader);
      mockClass = enhancer.createClass();
      // ///CLOVER:ON
    }

    try {
      Enhancer.registerCallbacks(mockClass, new Callback[] {interceptor});

      if (args != null) {
        // Really instantiate the class
        Constructor<?> cstr;
        try {
          // Get the constructor with the same params
          cstr = mockClass.getDeclaredConstructor(args.getConstructor().getParameterTypes());
        } catch (NoSuchMethodException e) {
          // Shouldn't happen, constructor is checked when ConstructorArgs is instantiated
          // ///CLOVER:OFF
          throw new RuntimeException("Fail to find constructor for param types", e);
          // ///CLOVER:ON
        }
        T mock;
        try {
          cstr.setAccessible(true); // So we can call a protected
          // constructor
          mock = (T) cstr.newInstance(args.getInitArgs());
        } catch (InstantiationException e) {
          // ///CLOVER:OFF
          throw new RuntimeException("Failed to instantiate mock calling constructor", e);
          // ///CLOVER:ON
        } catch (IllegalAccessException e) {
          // ///CLOVER:OFF
          throw new RuntimeException("Failed to instantiate mock calling constructor", e);
          // ///CLOVER:ON
        } catch (InvocationTargetException e) {
          throw new RuntimeException(
              "Failed to instantiate mock calling constructor: Exception in constructor",
              e.getTargetException());
        }
        return mock;
      } else {
        // Do not call any constructor

        Factory mock;
        try {
          mock = (Factory) ClassInstantiatorFactory.getInstantiator().newInstance(mockClass);
        } catch (InstantiationException e) {
          // ///CLOVER:OFF
          throw new RuntimeException(
              "Fail to instantiate mock for "
                  + toMock
                  + " on "
                  + ClassInstantiatorFactory.getJVM()
                  + " JVM");
          // ///CLOVER:ON
        }

        // This call is required. CGlib has some "magic code" making sure a
        // callback is used by only one instance of a given class. So only
        // the
        // instance created right after registering the callback will get
        // it.
        // However, this is done in the constructor which I'm bypassing to
        // allow class instantiation without calling a constructor.
        // Fortunately, the "magic code" is also called in getCallback which
        // is
        // why I'm calling it here mock.getCallback(0);
        mock.getCallback(0);

        return (T) mock;
      }
    } finally {
      // To avoid CGLib out of memory issues
      Enhancer.registerCallbacks(mockClass, null);
    }
  }
  @Override
  public ExporterTask getExporter(String type, HibernateToolTask parent, String serviceName) {
    Enhancer enhancer = new Enhancer();
    enhancer.setCallbackType(ExporterTaskInterceptor.class);
    enhancer.setCallback(new ExporterTaskInterceptor());

    ExporterTask proxy = null;
    if (type.equals("config")) {
      enhancer.setSuperclass(HibernateConfigExporterTask.class);
      enhancer.setClassLoader(HibernateConfigExporterTask.class.getClassLoader());
      proxy =
          (HibernateConfigExporterTask)
              enhancer.create(
                  new Class[] {HibernateToolTask.class, Folder.class},
                  new Object[] {parent, this.destDir});
    } else if (type.equals("java")) {
      enhancer.setSuperclass(Hbm2JavaExporterTaskWrapper.class);
      enhancer.setClassLoader(Hbm2JavaExporterTaskWrapper.class.getClassLoader());
      proxy =
          (Hbm2JavaExporterTaskWrapper)
              enhancer.create(
                  new Class[] {HibernateToolTask.class, Folder.class},
                  new Object[] {parent, this.destDir});
    } else if (type.equals("query")) {
      enhancer.setSuperclass(QueryExporterTask.class);
      enhancer.setClassLoader(QueryExporterTask.class.getClassLoader());
      proxy =
          (QueryExporterTask)
              enhancer.create(
                  new Class[] {HibernateToolTask.class, String.class, Folder.class},
                  new Object[] {parent, serviceName, this.destDir});
    } else if (type.equals("mapping")) {
      enhancer.setSuperclass(Hbm2HbmXmlExporterTaskWrapper.class);
      enhancer.setClassLoader(Hbm2HbmXmlExporterTaskWrapper.class.getClassLoader());
      proxy =
          (Hbm2HbmXmlExporterTaskWrapper)
              enhancer.create(
                  new Class[] {HibernateToolTask.class, Folder.class},
                  new Object[] {parent, this.destDir});
    } else if (type.equals("springConfig")) {
      enhancer.setSuperclass(HibernateSpringConfigExporterTask.class);
      enhancer.setClassLoader(HibernateSpringConfigExporterTask.class.getClassLoader());
      proxy =
          (HibernateSpringConfigExporterTask)
              enhancer.create(
                  new Class[] {
                    HibernateToolTask.class,
                    Folder.class,
                    String.class,
                    String.class,
                    String.class,
                    String.class,
                    boolean.class,
                    boolean.class,
                    String.class,
                    Integer.class
                  },
                  new Object[] {
                    parent,
                    this.destDir,
                    serviceName,
                    this.packageName,
                    this.dataPackage,
                    this.className,
                    this.useIndividualCRUDOperations,
                    this.impersonateUser,
                    this.activeDirectoryDomain,
                    this.batchSize
                  });
    }
    return proxy;
  }