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 extends Entry> 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 extends Entry> 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