All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.java.truevfs.kernel.impl.DisconnectingOutputService Maven / Gradle / Ivy

/*
 * Copyright © 2005 - 2021 Schlichtherle IT Services.
 * All rights reserved. Use is subject to license terms.
 */
package net.java.truevfs.kernel.impl;

import edu.umd.cs.findbugs.annotations.DischargesObligation;
import net.java.truecommons.cio.*;
import net.java.truecommons.io.ClosedOutputException;
import net.java.truecommons.io.ClosedStreamException;
import net.java.truecommons.io.DisconnectingOutputStream;
import net.java.truecommons.io.DisconnectingSeekableChannel;

import javax.annotation.WillCloseWhenClosed;
import javax.annotation.concurrent.NotThreadSafe;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.channels.SeekableByteChannel;
import java.util.Iterator;

/**
 * Decorates another output service in order to disconnect any resources when this output service gets closed.
 * Once {@link #close()}d, all methods of all products of this service, including all sockets, streams etc. but
 * excluding {@link #output(Entry)} and all {@code close()} methods of all products will throw a
 * {@link net.java.truecommons.io.ClosedOutputException} when called.
 *
 * @param  the type of the entries.
 * @author Christian Schlichtherle
 * @see DisconnectingInputService
 */
@NotThreadSafe
final class DisconnectingOutputService extends DecoratingOutputService {

    private final CheckedCloseable cc = new CheckedCloseable(container) {

        @Override
        ClosedStreamException newClosedStreamException() {
            return new ClosedOutputException();
        }
    };

    DisconnectingOutputService(@WillCloseWhenClosed OutputService output) {
        super(output);
    }

    @DischargesObligation
    @Override
    public void close() throws IOException {
        cc.close();
    }

    boolean isOpen() {
        return cc.isOpen();
    }

    @Override
    public int size() {
        return cc.checked(new Op() {

            @Override
            public Integer call() {
                return container.size();
            }
        });
    }

    @Override
    public Iterator iterator() {
        return cc.checked(new Op, RuntimeException>() {

            @Override
            public Iterator call() {
                return container.iterator();
            }
        });
    }

    @Override
    public E entry(String name) {
        return cc.checked(new Op() {

            @Override
            public E call() {
                return container.entry(name);
            }
        });
    }

    @Override
    public OutputSocket output(E entry) {
        return new AbstractOutputSocket() {

            private final OutputSocket socket = container.output(entry);

            @Override
            public E target() throws IOException {
                return cc.checked(new Op() {

                    @Override
                    public E call() throws IOException {
                        return socket.target();
                    }
                });
            }

            @Override
            public OutputStream stream(InputSocket peer) throws IOException {
                return new DisconnectingOutputStreamImpl(cc.checked(new Op() {

                    @Override
                    public OutputStream call() throws IOException {
                        return socket.stream(peer);
                    }
                }));
            }

            @Override
            public SeekableByteChannel channel(InputSocket peer) throws IOException {
                return new DisconnectingSeekableChannelImpl(cc.checked(new Op() {

                    @Override
                    public SeekableByteChannel call() throws IOException {
                        return socket.channel(peer);
                    }
                }));
            }
        };
    }

    private final class DisconnectingOutputStreamImpl extends DisconnectingOutputStream {

        DisconnectingOutputStreamImpl(@WillCloseWhenClosed OutputStream out) {
            super(out);
        }

        @Override
        public boolean isOpen() {
            return cc.isOpen();
        }

        @DischargesObligation
        @Override
        public void close() throws IOException {
            if (isOpen()) {
                out.close();
            }
        }
    }

    private final class DisconnectingSeekableChannelImpl extends DisconnectingSeekableChannel {

        DisconnectingSeekableChannelImpl(@WillCloseWhenClosed SeekableByteChannel channel) {
            super(channel);
        }

        @Override
        public boolean isOpen() {
            return cc.isOpen();
        }

        @DischargesObligation
        @Override
        public void close() throws IOException {
            if (isOpen()) {
                channel.close();
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy