CompileContext (final CompileContext delegate) { final UserDataHolderBase localDataHolder = new UserDataHolderBase(); final Set<Object> deletedKeysSet = ContainerUtil.newConcurrentSet(); final Class<UserDataHolder> dataHolderInterface = UserDataHolder.class; final Class<MessageHandler> messageHandlerInterface = MessageHandler.class; return ReflectionUtil.proxy(delegate.getClass().getClassLoader(), CompileContext.class, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (args != null) { final Class<?> declaringClass = method.getDeclaringClass(); if (dataHolderInterface.equals(declaringClass)) { final Object firstArgument = args[0]; if (!(firstArgument instanceof GlobalContextKey)) { final boolean isWriteOperation = args.length == 2 /*&& void.class.equals(method.getReturnType())*/; if (isWriteOperation) { if (args[1] == null) { deletedKeysSet.add(firstArgument); } else { deletedKeysSet.remove(firstArgument); } } else { if (deletedKeysSet.contains(firstArgument)) { return null; } } final Object result = method.invoke(localDataHolder, args); if (isWriteOperation || result != null) { return result; } } } else if (messageHandlerInterface.equals(declaringClass)) { final BuildMessage msg = (BuildMessage)args[0]; if (msg.getKind() == BuildMessage.Kind.ERROR) { Utils.ERRORS_DETECTED_KEY.set(localDataHolder, Boolean.TRUE); } } return MethodHandles.lookup().unreflect(method).bindTo(delegate).asSpreader(Object[].class, args.length).invoke(args); } return MethodHandles.lookup().unreflect(method).invoke(delegate); } }); }