Java源码示例:org.xnio.conduits.ConduitStreamSinkChannel
示例1
/**
* Get the response channel. The channel must be closed and fully flushed before the next response can be started.
* In order to close the channel you must first call {@link org.xnio.channels.StreamSinkChannel#shutdownWrites()},
* and then call {@link org.xnio.channels.StreamSinkChannel#flush()} until it returns true. Alternatively you can
* call {@link #endExchange()}, which will close the channel as part of its cleanup.
* <p>
* Closing a fixed-length response before the corresponding number of bytes has been written will cause the connection
* to be reset and subsequent requests to fail; thus it is important to ensure that the proper content length is
* delivered when one is specified. The response channel may not be writable until after the response headers have
* been sent.
* <p>
* If this method is not called then an empty or default response body will be used, depending on the response code set.
* <p>
* The returned channel will begin to write out headers when the first write request is initiated, or when
* {@link org.xnio.channels.StreamSinkChannel#shutdownWrites()} is called on the channel with no content being written.
* Once the channel is acquired, however, the response code and headers may not be modified.
* <p>
*
* @return the response channel, or {@code null} if another party already acquired the channel
*/
public StreamSinkChannel getResponseChannel() {
if (responseChannel != null) {
return null;
}
final ConduitWrapper<StreamSinkConduit>[] wrappers = responseWrappers;
this.responseWrappers = null;
final ConduitStreamSinkChannel sinkChannel = connection.getSinkChannel();
if (sinkChannel == null) {
return null;
}
if(wrappers != null) {
final WrapperStreamSinkConduitFactory factory = new WrapperStreamSinkConduitFactory(wrappers, responseWrapperCount, this, sinkChannel.getConduit());
sinkChannel.setConduit(factory.create());
} else {
sinkChannel.setConduit(connection.getSinkConduit(this, sinkChannel.getConduit()));
}
this.responseChannel = new WriteDispatchChannel(sinkChannel);
this.startResponse();
return responseChannel;
}
示例2
@Override
public ConduitStreamSinkChannel getSinkChannel() {
ConduitStreamSinkChannel sinkChannel = new ConduitStreamSinkChannel(
Configurable.EMPTY,
new BufferedStreamSinkConduit(
new NullStreamSinkConduit(worker.getIoThread()),
new PooledAdaptor(bufferPool.allocate())
)
);
sinkChannel.setCloseListener(conduitStreamSinkChannel -> {
for (CloseListener l : closeListeners) {
try {
l.closed(InVMConnection.this);
} catch (Throwable e) {
UndertowLogger.REQUEST_LOGGER.exceptionInvokingCloseListener(l, e);
}
}
});
return sinkChannel;
}
示例3
@Override
public ConduitStreamSinkChannel getSinkChannel() {
ConduitStreamSinkChannel sinkChannel = new ConduitStreamSinkChannel(
Configurable.EMPTY,
new BufferedStreamSinkConduit(
new NullStreamSinkConduit(worker.getIoThread()),
new PooledAdaptor(bufferPool.allocate())
)
);
sinkChannel.setCloseListener(conduitStreamSinkChannel -> {
for (CloseListener l : closeListeners) {
try {
l.closed(InVMConnection.this);
} catch (Throwable e) {
UndertowLogger.REQUEST_LOGGER.exceptionInvokingCloseListener(l, e);
}
}
});
return sinkChannel;
}
示例4
@Override
public void writeReady() {
if(anyAreSet(state, FLAG_READ_REQUIRES_WRITE)) {
if(anyAreSet(state, FLAG_READS_RESUMED)) {
readReadyHandler.readReady();
} else {
try {
doHandshake();
} catch (IOException e) {
UndertowLogger.REQUEST_LOGGER.ioException(e);
IoUtils.safeClose(delegate);
} catch (Throwable t) {
UndertowLogger.REQUEST_LOGGER.handleUnexpectedFailure(t);
IoUtils.safeClose(delegate);
}
}
}
if (anyAreSet(state, FLAG_WRITES_RESUMED)) {
if(delegateHandler == null) {
final ChannelListener<? super ConduitStreamSinkChannel> writeListener = connection.getSinkChannel().getWriteListener();
if (writeListener == null) {
suspendWrites();
} else {
ChannelListeners.invokeChannelListener(connection.getSinkChannel(), writeListener);
}
} else {
delegateHandler.writeReady();
}
}
if(!anyAreSet(state, FLAG_WRITES_RESUMED | FLAG_READ_REQUIRES_WRITE)) {
delegate.getSinkChannel().suspendWrites();
}
}
示例5
public Http2ServerConnection(Http2Channel channel, Http2StreamSourceChannel requestChannel, OptionMap undertowOptions, int bufferSize, HttpHandler rootHandler) {
this.channel = channel;
this.requestChannel = requestChannel;
this.undertowOptions = undertowOptions;
this.bufferSize = bufferSize;
this.rootHandler = rootHandler;
responseChannel = requestChannel.getResponseChannel();
originalSinkConduit = new StreamSinkChannelWrappingConduit(responseChannel);
originalSourceConduit = new StreamSourceChannelWrappingConduit(requestChannel);
this.conduitStreamSinkChannel = new ConduitStreamSinkChannel(responseChannel, originalSinkConduit);
this.conduitStreamSourceChannel = new ConduitStreamSourceChannel(channel, originalSourceConduit);
}
示例6
/**
* Channel that is used when the request is already half closed
* @param channel
* @param undertowOptions
* @param bufferSize
* @param rootHandler
*/
public Http2ServerConnection(Http2Channel channel, Http2DataStreamSinkChannel sinkChannel, OptionMap undertowOptions, int bufferSize, HttpHandler rootHandler) {
this.channel = channel;
this.rootHandler = rootHandler;
this.requestChannel = null;
this.undertowOptions = undertowOptions;
this.bufferSize = bufferSize;
responseChannel = sinkChannel;
originalSinkConduit = new StreamSinkChannelWrappingConduit(responseChannel);
originalSourceConduit = new StreamSourceChannelWrappingConduit(requestChannel);
this.conduitStreamSinkChannel = new ConduitStreamSinkChannel(responseChannel, originalSinkConduit);
this.conduitStreamSourceChannel = new ConduitStreamSourceChannel(Configurable.EMPTY, new EmptyStreamSourceConduit(getIoThread()));
}
示例7
@Override
public ChannelListener.Setter<? extends StreamSinkChannel> getWriteSetter() {
if (writeSetter == null) {
writeSetter = new ChannelListener.SimpleSetter<>();
if (!isFinished()) {
if(delegate instanceof ConduitStreamSinkChannel) {
((ConduitStreamSinkChannel) delegate).setWriteListener(new SetterDelegatingListener((ChannelListener.SimpleSetter)writeSetter, this));
} else {
delegate.getWriteSetter().set(new SetterDelegatingListener((ChannelListener.SimpleSetter)writeSetter, this));
}
}
}
return writeSetter;
}
示例8
public void responseDone() {
if(delegate instanceof ConduitStreamSinkChannel) {
((ConduitStreamSinkChannel) delegate).setCloseListener(null);
((ConduitStreamSinkChannel) delegate).setWriteListener(null);
} else {
delegate.getCloseSetter().set(null);
delegate.getWriteSetter().set(null);
}
if (delegate.isWriteResumed()) {
delegate.suspendWrites();
}
}
示例9
private void setOpWrite() {
ConduitStreamSinkChannel sink = connection().getSinkChannel();
if (!sink.isWriteResumed()) {
ChannelListener<ConduitStreamSinkChannel> writeListener = this.writeListener;
if (writeListener == null) {
writeListener = this.writeListener = new WriteListener();
}
sink.getWriteSetter().set(writeListener);
sink.resumeWrites();
}
}
示例10
@Override
public ConduitStreamSinkChannel getSinkChannel() {
return null;
}
示例11
private void initiateRequest(HttpClientExchange httpClientExchange) {
this.requestCount++;
currentRequest = httpClientExchange;
pendingResponse = new HttpResponseBuilder();
ClientRequest request = httpClientExchange.getRequest();
String connectionString = request.getRequestHeaders().getFirst(Headers.CONNECTION);
if (connectionString != null) {
if (Headers.CLOSE.equalToString(connectionString)) {
state |= CLOSE_REQ;
} else if (Headers.UPGRADE.equalToString(connectionString)) {
state |= UPGRADE_REQUESTED;
}
} else if (request.getProtocol() != Protocols.HTTP_1_1) {
state |= CLOSE_REQ;
}
if (request.getRequestHeaders().contains(Headers.UPGRADE)) {
state |= UPGRADE_REQUESTED;
}
if(request.getMethod().equals(Methods.CONNECT)) {
//we treat CONNECT like upgrade requests
state |= UPGRADE_REQUESTED;
}
//setup the client request conduits
final ConduitStreamSourceChannel sourceChannel = connection.getSourceChannel();
sourceChannel.setReadListener(clientReadListener);
sourceChannel.resumeReads();
ConduitStreamSinkChannel sinkChannel = connection.getSinkChannel();
StreamSinkConduit conduit = originalSinkConduit;
HttpRequestConduit httpRequestConduit = new HttpRequestConduit(conduit, bufferPool, request);
httpClientExchange.setRequestConduit(httpRequestConduit);
conduit = httpRequestConduit;
String fixedLengthString = request.getRequestHeaders().getFirst(Headers.CONTENT_LENGTH);
String transferEncodingString = request.getRequestHeaders().getLast(Headers.TRANSFER_ENCODING);
boolean hasContent = true;
if (fixedLengthString != null) {
try {
long length = Long.parseLong(fixedLengthString);
conduit = new ClientFixedLengthStreamSinkConduit(conduit, length, false, false, currentRequest);
hasContent = length != 0;
} catch (NumberFormatException e) {
handleError(e);
return;
}
} else if (transferEncodingString != null) {
if (!transferEncodingString.toLowerCase(Locale.ENGLISH).contains(Headers.CHUNKED.toString())) {
handleError(UndertowClientMessages.MESSAGES.unknownTransferEncoding(transferEncodingString));
return;
}
conduit = new ChunkedStreamSinkConduit(conduit, httpClientExchange.getConnection().getBufferPool(), false, false, httpClientExchange.getRequest().getRequestHeaders(), requestFinishListener, httpClientExchange);
} else {
conduit = new ClientFixedLengthStreamSinkConduit(conduit, 0, false, false, currentRequest);
hasContent = false;
}
sinkChannel.setConduit(conduit);
httpClientExchange.invokeReadReadyCallback();
if (!hasContent) {
//if there is no content we flush the response channel.
//otherwise it is up to the user
try {
sinkChannel.shutdownWrites();
if (!sinkChannel.flush()) {
sinkChannel.setWriteListener(ChannelListeners.flushingChannelListener(null, new ChannelExceptionHandler<ConduitStreamSinkChannel>() {
@Override
public void handleException(ConduitStreamSinkChannel channel, IOException exception) {
handleError(exception);
}
}));
sinkChannel.resumeWrites();
}
} catch (Throwable t) {
handleError(t);
}
}
}
示例12
@Override
protected ConduitStreamSinkChannel getSinkChannel() {
return channel.getSinkChannel();
}
示例13
public static ConduitStreamSinkChannel getConduitSinkChannel(HttpServerExchange exchange) {
return exchange.getConnection().getSinkChannel();
}
示例14
@Override
protected ConduitStreamSinkChannel getSinkChannel() {
return conduitStreamSinkChannel;
}
示例15
/**
* Gets a pre-encoded resource.
* <p>
* TODO: blocking / non-blocking semantics
*
* @param resource
* @param exchange
* @return
* @throws IOException
*/
public ContentEncodedResource getResource(final Resource resource, final HttpServerExchange exchange) throws IOException {
final String path = resource.getPath();
Path file = resource.getFilePath();
if (file == null) {
return null;
}
if (minResourceSize > 0 && resource.getContentLength() < minResourceSize ||
maxResourceSize > 0 && resource.getContentLength() > maxResourceSize ||
!(encodingAllowed == null || encodingAllowed.resolve(exchange))) {
return null;
}
AllowedContentEncodings encodings = contentEncodingRepository.getContentEncodings(exchange);
if (encodings == null || encodings.isNoEncodingsAllowed()) {
return null;
}
EncodingMapping encoding = encodings.getEncoding();
if (encoding == null || encoding.getName().equals(ContentEncodingRepository.IDENTITY)) {
return null;
}
String newPath = path + ".undertow.encoding." + encoding.getName();
Resource preCompressed = encoded.getResource(newPath);
if (preCompressed != null) {
return new ContentEncodedResource(preCompressed, encoding.getName());
}
final LockKey key = new LockKey(path, encoding.getName());
if (fileLocks.putIfAbsent(key, this) != null) {
//another thread is already compressing
//we don't do anything fancy here, just return and serve non-compressed content
return null;
}
FileChannel targetFileChannel = null;
FileChannel sourceFileChannel = null;
try {
//double check, the compressing thread could have finished just before we acquired the lock
preCompressed = encoded.getResource(newPath);
if (preCompressed != null) {
return new ContentEncodedResource(preCompressed, encoding.getName());
}
final Path finalTarget = encodedResourcesRoot.resolve(newPath);
final Path tempTarget = encodedResourcesRoot.resolve(newPath);
//horrible hack to work around XNIO issue
OutputStream tmp = Files.newOutputStream(tempTarget);
try {
tmp.close();
} finally {
IoUtils.safeClose(tmp);
}
targetFileChannel = FileChannel.open(tempTarget, StandardOpenOption.READ, StandardOpenOption.WRITE);
sourceFileChannel = FileChannel.open(file, StandardOpenOption.READ);
StreamSinkConduit conduit = encoding.getEncoding().getResponseWrapper().wrap(new ImmediateConduitFactory<StreamSinkConduit>(new FileConduitTarget(targetFileChannel, exchange)), exchange);
final ConduitStreamSinkChannel targetChannel = new ConduitStreamSinkChannel(null, conduit);
long transferred = sourceFileChannel.transferTo(0, resource.getContentLength(), targetChannel);
targetChannel.shutdownWrites();
org.xnio.channels.Channels.flushBlocking(targetChannel);
if (transferred != resource.getContentLength()) {
UndertowLogger.REQUEST_LOGGER.failedToWritePreCachedFile();
}
Files.move(tempTarget, finalTarget);
encoded.invalidate(newPath);
final Resource encodedResource = encoded.getResource(newPath);
return new ContentEncodedResource(encodedResource, encoding.getName());
} finally {
IoUtils.safeClose(targetFileChannel);
IoUtils.safeClose(sourceFileChannel);
fileLocks.remove(key);
}
}
示例16
WriteDispatchChannel(final ConduitStreamSinkChannel delegate) {
super(delegate);
}
示例17
@Override
public void handleEvent(ConduitStreamSinkChannel channel) {
((AbstractXnioUnsafe)unsafe()).forceFlush();
}
示例18
protected abstract ConduitStreamSinkChannel getSinkChannel();