package org.glassfish.grizzly.http.server.io;
import java.io.File;
import java.util.concurrent.Executor;
import java.util.logging.Level;
import org.glassfish.grizzly.CompletionHandler;
import org.glassfish.grizzly.WriteResult;
import org.glassfish.grizzly.filterchain.FilterChainContext;
import org.glassfish.grizzly.http.io.OutputBuffer;
import org.glassfish.grizzly.http.server.Response;
import org.glassfish.grizzly.localization.LogMessages;
public class ServerOutputBuffer extends OutputBuffer {
private Response serverResponse;
public void initialize(final Response response, final FilterChainContext ctx) {
super.initialize(response.getResponse(), response.isSendFileEnabled(), ctx);
this.serverResponse = response;
}
@Override
public void sendfile(final File file, final long offset, final long length, final CompletionHandler<WriteResult> handler) {
if (!sendfileEnabled) {
throw new IllegalStateException("sendfile support isn't available.");
}
final boolean suspendedAtStart = serverResponse.isSuspended();
final CompletionHandler<WriteResult> ch;
if (suspendedAtStart && handler != null) {
ch = handler;
} else if (!suspendedAtStart && handler != null) {
ch = suspendAndCreateHandler(handler);
} else {
ch = createInternalCompletionHandler(file, suspendedAtStart);
}
super.sendfile(file, offset, length, ch);
}
@Override
public void recycle() {
serverResponse = null;
super.recycle();
}
@Override
protected Executor getThreadPool() {
return serverResponse.getRequest().getRequestExecutor();
}
private CompletionHandler<WriteResult> createInternalCompletionHandler(final File file, final boolean suspendedAtStart) {
CompletionHandler<WriteResult> ch;
if (!suspendedAtStart) {
serverResponse.suspend();
}
ch = new CompletionHandler<WriteResult>() {
@Override
public void cancelled() {
if (LOGGER.isLoggable(Level.WARNING)) {
LOGGER.log(Level.WARNING, LogMessages.WARNING_GRIZZLY_HTTP_SERVER_SERVEROUTPUTBUFFER_FILE_TRANSFER_CANCELLED(file.getAbsolutePath()));
}
serverResponse.resume();
}
@Override
public void failed(Throwable throwable) {
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.log(Level.SEVERE,
LogMessages.WARNING_GRIZZLY_HTTP_SERVER_SERVEROUTPUTBUFFER_FILE_TRANSFER_FAILED(file.getAbsolutePath(), throwable.getMessage()),
throwable);
}
serverResponse.resume();
}
@Override
public void completed(WriteResult result) {
serverResponse.resume();
}
@Override
public void updated(WriteResult result) {
}
};
return ch;
}
private CompletionHandler<WriteResult> suspendAndCreateHandler(final CompletionHandler<WriteResult> handler) {
serverResponse.suspend();
return new CompletionHandler<WriteResult>() {
@Override
public void cancelled() {
handler.cancelled();
serverResponse.resume();
}
@Override
public void failed(Throwable throwable) {
handler.failed(throwable);
serverResponse.resume();
}
@Override
public void completed(WriteResult result) {
handler.completed(result);
serverResponse.resume();
}
@Override
public void updated(WriteResult result) {
handler.updated(result);
}
};
}
}