public static <T> T proxy(Class<T> type, Callback callback) {
    callback = callback != null ? callback : BLOCKER;

    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(type);
    enhancer.setCallbackType(callback.getClass());

    @SuppressWarnings("unchecked")
    Class<T> proxyClass = enhancer.createClass();

    @SuppressWarnings("unchecked")
    T proxy = (T) ObjenesisHelper.newInstance(proxyClass);
    ((Factory) proxy).setCallback(0, callback);
    return proxy;
  }
예제 #2
0
  private Factory createMock() throws Exception {
    final MethodInterceptor interceptor =
        new MethodInterceptor() {
          public Object intercept(
              final Object obj, final Method method, final Object[] args, final MethodProxy proxy)
              throws Throwable {
            return proxy.invokeSuper(obj, args);
          }
        };

    final Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(ArrayList.class);
    enhancer.setCallbackType(MethodInterceptor.class);

    final Class<?> mockClass = enhancer.createClass();

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

    final Factory f = (Factory) ClassInstantiatorFactory.getInstantiator().newInstance(mockClass);

    f.getCallback(0);

    return f;
  }
예제 #3
0
  @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);
    }
  }
예제 #4
0
  @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;
  }