@Override
	public Object invoke( Object object, Method method, Object[] arguments ) throws Throwable
	{
		assert object.getClass() == interfaceClass;
		assert targetClients != null;

		final MethodMeta meta = remoteMethods.get( method );
		
		if (meta != null)
		{
		    final RemoteMethodCall call = new RemoteMethodCall();
			call.remoteInterface = remoteInterface;
			call.remoteMethod = meta.remoteMethod;
			call.reflectMethod = meta.reflectMethod;
			call.arguments = arguments;
			call.timestamp = System.nanoTime();
			call.retries = meta.remoteMethod.retryCount();
			call.callSize = meta.reflectMethod.sizeOf( arguments );

			final Match writeMatch = meta.remoteMethod.writeMatch();
			final int writeStates = meta.remoteMethod.writeStates();
			
			for (Client client : targetClients)
			{
				if (writeMatch.isMatch( writeStates, client.getStates() ) || 
				   !client.getProtocol().notifyWriteBlock(client, writeMatch, writeStates, client.getStates()))
				{
					client.queue( call );
				}
			}
		}
		else
		{
		    return method.invoke( object, arguments );
		}

		return null;
	}