@Override
    public AttributedList<Path> run(final Session<?> session) throws BackgroundException {
        try {
            final AttributedList<Path> list;
            listener.reset();
            if(this.isCached()) {
                list = cache.get(directory);
                listener.chunk(directory, list);
            }
            else {
                final ListService service = session.getFeature(ListService.class);
                if(log.isDebugEnabled()) {
                    log.debug(String.format("Run with feature %s", service));
                }
                list = service.list(directory, listener);
                if(list.isEmpty()) {
                    listener.chunk(directory, list);
                }
                if(log.isDebugEnabled()) {
                    log.debug(String.format("Notify listener %s", listener));
                }
            }
            listener.finish(directory, list, Optional.empty());
            return list;
        }
        catch(ListCanceledException e) {
            if(log.isWarnEnabled()) {
                log.warn(String.format("Return partial directory listing for %s", directory));
            }
            listener.finish(directory, e.getChunk(), Optional.of(e));
            return e.getChunk();
        }
        catch(BackgroundException e) {
            if(log.isWarnEnabled()) {
                log.warn(String.format("Notify listener for %s with error %s", directory, e));
            }
            listener.finish(directory, AttributedList.emptyList(), Optional.of(e));
            throw e;
        }
    }
@Test
    public void testCacheListCanceledWithController() throws Exception {
        final Host host = new Host(new TestProtocol(), "localhost");
        final Session<?> session = new NullSession(host) {
            @Override
            public AttributedList<Path> list(final Path directory, final ListProgressListener listener) throws BackgroundException {
                throw new ListCanceledException(AttributedList.emptyList());
            }
        };
        final PathCache cache = new PathCache(1);
        final Path directory = new Path("/home/notfound", EnumSet.of(Path.Type.directory));
        cache.put(directory, new AttributedList<>(Collections.singletonList(new Path(directory, "f", EnumSet.of(Path.Type.file)))));
        final ListWorker worker = new ListWorker(cache,
                directory,
                new DisabledListProgressListener());
        final Controller c = new AbstractController() {
            @Override
            public void invoke(final MainAction runnable, final boolean wait) {
                runnable.run();
            }
        };
        final Future<AttributedList<Path>> task = c.background(new WorkerBackgroundAction<>(c, new StatelessSessionPool(
                new TestLoginConnectionService(), session,
                new DisabledTranscriptListener(), new DefaultVaultRegistry(new DisabledPasswordCallback())), worker));
        assertNotNull(task.get());
        assertTrue(cache.containsKey(directory));
        assertEquals(1, cache.get(directory).size());
    }