/* Copyright (c) 2014 Boundless and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/edl-v10.html
*
* Contributors:
* Gabriel Roldan (Boundless) - initial implementation
*/
package org.locationtech.geogig.rest.repository;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.WritableByteChannel;
import org.restlet.Context;
import org.restlet.data.ClientInfo;
import org.restlet.data.Encoding;
import org.restlet.resource.Representation;
import org.restlet.util.ByteUtils;
import com.noelios.restlet.application.EncodeRepresentation;
import com.noelios.restlet.application.Encoder;
/**
* Extends {@link Encoder} in order to overcome the bug that leaves a dangling non-daemon thread for
* each response written product of {@link EncodeRepresentation#getStream()} (see
* {@link ByteUtils#getStream(Representation)}.
*
* <p>
* To do so, we forbid calls to {@link EncodeRepresentation#getStream()} and instead override
* {@link EncodeRepresentation#write(WritableByteChannel)}.
*
* <p>
* NOTE: this class can be removed if/when we upgrade to a restlet version > 2.x which seems to have
* fixed this issue.
*/
public class FixedEncoder extends Encoder {
public FixedEncoder(Context context) {
super(context);
}
@Override
public Representation encode(ClientInfo client, Representation representation) {
Representation result = representation;
Encoding bestEncoding = getBestEncoding(client);
if (bestEncoding != null && !Encoding.IDENTITY.equals(bestEncoding)) {
result = new FixedEncoderRepresentation(bestEncoding, representation);
}
return result;
}
private static final class FixedEncoderRepresentation extends EncodeRepresentation {
public FixedEncoderRepresentation(Encoding encoding, Representation wrappedRepresentation) {
super(encoding, wrappedRepresentation);
}
@Override
public InputStream getStream() throws IOException {
throw new UnsupportedOperationException(
"shouldn't be called, we implement write(WBC) without calling this method");
}
@Override
public void write(WritableByteChannel writableChannel) throws IOException {
if (canEncode()) {
OutputStream stream;
stream = org.restlet.util.ByteUtils.getStream(writableChannel);
write(stream);
} else {
getWrappedRepresentation().write(writableChannel);
}
}
}
}