package org.couchbase.mock.http;
import org.apache.http.*;
import org.apache.http.entity.ContentType;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;
import org.couchbase.mock.Bucket;
import org.couchbase.mock.CouchbaseMock;
import org.couchbase.mock.JsonUtils;
import org.couchbase.mock.http.capi.CAPIServer;
import org.couchbase.mock.httpio.HandlerUtil;
import org.couchbase.mock.httpio.HttpServer;
import org.couchbase.mock.httpio.ResponseHandledException;
import org.couchbase.mock.memcached.MemcachedServer;
import java.io.IOException;
import java.net.Socket;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public final class BucketAdminServer {
private final CouchbaseMock mock;
private final HttpAuthVerifier verifier;
private final Bucket bucket;
private final HttpServer parentServer;
private class StreamingHandler implements HttpRequestHandler {
@Override
public void handle(HttpRequest req, HttpResponse response, HttpContext context) throws HttpException, IOException {
if (!verifier.verify(req, response, context)) {
return;
}
HttpServerConnection htConn = HandlerUtil.getConnection(context);
response.setHeader(HttpHeaders.TRANSFER_ENCODING, HTTP.CHUNK_CODING);
response.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString());
response.setHeader(HttpHeaders.CONNECTION, HTTP.CONN_CLOSE);
response.removeHeaders(HttpHeaders.CONTENT_LENGTH);
// Write the response
htConn.sendResponseHeader(response);
htConn.flush();
Socket s = HandlerUtil.getSocket(context);
BucketsStreamingHandler streamingHandler = new BucketsStreamingHandler(mock.getMonitor(),bucket, s);
try {
streamingHandler.startStreaming();
} catch (InterruptedException ex) {
throw new IOException(ex);
}
// Ensure it doesn't get processed
throw new ResponseHandledException();
}
}
private class OneShotHandler implements HttpRequestHandler {
public void handle(HttpRequest req, HttpResponse response, HttpContext context) throws HttpException, IOException {
if (!verifier.verify(req, response, context)) {
return;
}
String methodName = req.getRequestLine().getMethod();
if (methodName.equals("GET")) {
HandlerUtil.makeJsonResponse(response, StateGrabber.getBucketJSON(bucket));
} else if (methodName.equals("DELETE")) {
mock.getPoolsHandler().handleDeleteBucket(req, response, context, bucket);
} else {
response.setStatusCode(HttpStatus.SC_NOT_IMPLEMENTED);
}
}
}
private class FlushHandler implements HttpRequestHandler {
@Override
public void handle(HttpRequest req, HttpResponse response, HttpContext context) throws HttpException, IOException {
if (!verifier.verify(req, response, context)) {
return;
}
for (MemcachedServer server : bucket.getServers()) {
server.flushAll();
}
}
}
private class DesignDocsHandler implements HttpRequestHandler {
@Override
public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
if (!verifier.verify(request, response, context)) {
return;
}
CAPIServer capi = bucket.getCAPIServer();
if (capi == null) {
HandlerUtil.makeStringResponse(response, "Not found");
response.setStatusCode(HttpStatus.SC_NOT_FOUND);
return;
}
Map<String,Object> ddInfo = capi.getDddocApiInfo();
String encoded = JsonUtils.encode(ddInfo);
HandlerUtil.makeJsonResponse(response, encoded);
}
}
public BucketAdminServer(Bucket bucket, HttpServer server, CouchbaseMock mock) {
this.bucket = bucket;
this.mock = mock;
this.parentServer = server;
this.verifier = new HttpAuthVerifier(bucket, mock.getAuthenticator());
}
private static final String FMT_ONESHOT = "%s/buckets/%s";
private static final String FMT_STREAM = "%s/bucketsStreaming/%s";
private static final String FMT_DOFLUSH = "%s/buckets/%s/controller/doFlush";
private static final String FMT_DDOCS = "%s/buckets/%s/ddocs";
private String getPoolPrefix() {
return String.format("/pools/%s", mock.getPoolName());
}
public void register() {
String prefix = getPoolPrefix();
parentServer.register(String.format(FMT_ONESHOT, prefix, bucket.getName()), new OneShotHandler());
parentServer.register(String.format(FMT_STREAM, prefix, bucket.getName()), new StreamingHandler());
parentServer.register(String.format(FMT_DOFLUSH, prefix, bucket.getName()), new FlushHandler());
parentServer.register(String.format(FMT_DDOCS, prefix, bucket.getName()), new DesignDocsHandler());
}
public void shutdown() {
String prefix = getPoolPrefix();
for (String s : new String[] { FMT_ONESHOT, FMT_STREAM, FMT_DOFLUSH, FMT_DDOCS}) {
String path = String.format(s, prefix, bucket.getName());
parentServer.unregister(path);
}
}
}