/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.glowroot.agent.plugin.redis;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static java.util.concurrent.TimeUnit.SECONDS;
class RedisMockServer implements Runnable {
private static final Logger logger = LoggerFactory.getLogger(RedisMockServer.class);
private final ExecutorService executor = Executors.newCachedThreadPool();
private final ServerSocket server;
private int port;
private boolean stop;
RedisMockServer() throws IOException {
server = new ServerSocket(0);
port = server.getLocalPort();
executor.execute(this);
}
@Override
public void run() {
try {
runInternal();
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
int getPort() {
return port;
}
void close() throws InterruptedException {
stop = true;
executor.shutdown();
executor.awaitTermination(10, SECONDS);
}
private void runInternal() throws IOException {
while (!stop) {
Socket socket = server.accept();
executor.execute(new CallResponseProxy(socket));
}
}
private class CallResponseProxy implements Runnable {
private Socket socket;
CallResponseProxy(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
runInternal();
} catch (IOException e) {
if (!stop) {
logger.error(e.getMessage(), e);
}
}
}
private void runInternal() throws IOException, UnsupportedEncodingException {
byte[] request = new byte[1024];
InputStream socketIn = socket.getInputStream();
OutputStream socketOut = socket.getOutputStream();
int nBytes;
while ((nBytes = socketIn.read(request)) != -1) {
String command = new String(request, 0, nBytes, "UTF-8").replaceAll("\r\n", " ");
String response = getResponse(command);
socketOut.write(response.getBytes());
}
}
private String getResponse(String command) {
if (command.equals("*1 $4 PING ")) {
return "+PONG\r\n";
} else if (command.equals("*2 $3 GET $3 key ")) {
return "$5\r\nvalue\r\n";
} else if (command.equals("*3 $3 SET $3 key $5 value ")) {
return "+OK\r\n";
} else {
return "+OK\r\n";
}
}
}
}