Esempio n. 1
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;
  }
  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;
  }
Esempio n. 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);
    }
  }