diff --git a/README.md b/README.md
index a29cf97..b400bee 100644
--- a/README.md
+++ b/README.md
@@ -7,12 +7,29 @@ Jedis was conceived to be EASY to use and FULLY COMPATIBLE with the latest versi
Jedis is a WORK IN PROGRESS.
## What's still missing?
-Right now almost everything. You can just PING, GET and SET. But stay close because whenever I have a couple of free hours it will support almost everything!
+- Commands operating on string values
+- Commands operating on lists
+- Commands operating on sets
+- Commands operating on sorted sets
+- Commands operating on hashes
+- Sorting
+- Transactions
+- Publish/Subscribe
+- Persistence control commands
+- Remote server control commands
+- And the AUTH command
+
+But stay close because things are going fast and all this will be implemented soon!
+
+## Ok.. so what's already done?
+- Connection handling (not AUTH)
+- Commands operating on all the kind of values
+- Commands operating on string values (just GET and SET)
## How do I use it?
You can download the latests build at:
- http://github.com/downloads/xetorthio/jedis/jedis-0.0.1-SNAPSHOT.jar
+ http://github.com/downloads/xetorthio/jedis/jedis-0.0.2.jar
To use it just:
diff --git a/pom.xml b/pom.xml
index 2cc762e..85c54aa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,7 +2,7 @@
4.0.0
redis.clients
jedis
- 0.0.1-SNAPSHOT
+ 0.0.2
junit
diff --git a/src/main/java/redis/clients/jedis/Client.java b/src/main/java/redis/clients/jedis/Client.java
index d362a94..6114595 100644
--- a/src/main/java/redis/clients/jedis/Client.java
+++ b/src/main/java/redis/clients/jedis/Client.java
@@ -5,6 +5,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
+import java.util.List;
public class Client {
private String host;
@@ -74,12 +75,19 @@ public class Client {
return connected;
}
- protected String getSingleLineReply() {
+ protected String getStatusCodeReply() throws JedisException {
return protocol.getSingleLineReply(inputStream);
}
- public String getBulkReply() {
+ public String getBulkReply() throws JedisException {
return protocol.getBulkReply(inputStream);
}
+ public int getIntegerReply() throws JedisException {
+ return protocol.getIntegerReply(inputStream);
+ }
+
+ public List getMultiBulkReply() throws JedisException {
+ return protocol.getMultiBulkReply(inputStream);
+ }
}
\ No newline at end of file
diff --git a/src/main/java/redis/clients/jedis/Jedis.java b/src/main/java/redis/clients/jedis/Jedis.java
index 89f3c9a..59ce924 100644
--- a/src/main/java/redis/clients/jedis/Jedis.java
+++ b/src/main/java/redis/clients/jedis/Jedis.java
@@ -1,21 +1,89 @@
package redis.clients.jedis;
+import java.util.List;
+
public class Jedis extends Client {
public Jedis(String host) {
super(host);
}
- public String ping() {
- return sendCommand("PING").getSingleLineReply();
+ public String ping() throws JedisException {
+ return sendCommand("PING").getStatusCodeReply();
}
- public String set(String key, String value) {
- return sendCommand("SET", key, value).getSingleLineReply();
-
+ public String set(String key, String value) throws JedisException {
+ return sendCommand("SET", key, value).getStatusCodeReply();
}
- public String get(String key) {
+ public String get(String key) throws JedisException {
return sendCommand("GET", key).getBulkReply();
}
+ public void quit() {
+ sendCommand("QUIT");
+ }
+
+ public int exists(String key) throws JedisException {
+ return sendCommand("EXISTS", key).getIntegerReply();
+ }
+
+ public int del(String... keys) throws JedisException {
+ return sendCommand("DEL", keys).getIntegerReply();
+ }
+
+ public String type(String key) throws JedisException {
+ return sendCommand("TYPE", key).getStatusCodeReply();
+ }
+
+ public String flushDB() throws JedisException {
+ return sendCommand("FLUSHDB").getStatusCodeReply();
+ }
+
+ public List keys(String pattern) throws JedisException {
+ return sendCommand("KEYS", pattern).getMultiBulkReply();
+ }
+
+ public String randomKey() throws JedisException {
+ return sendCommand("RANDOMKEY").getStatusCodeReply();
+ }
+
+ public String rename(String oldkey, String newkey) throws JedisException {
+ return sendCommand("RENAME", oldkey, newkey).getStatusCodeReply();
+ }
+
+ public int renamenx(String oldkey, String newkey) throws JedisException {
+ return sendCommand("RENAMENX", oldkey, newkey).getIntegerReply();
+ }
+
+ public int dbSize() throws JedisException {
+ return sendCommand("DBSIZE").getIntegerReply();
+ }
+
+ public int expire(String key, int seconds) throws JedisException {
+ return sendCommand("EXPIRE", key, String.valueOf(seconds))
+ .getIntegerReply();
+ }
+
+ public int expireAt(String key, long unixTime) throws JedisException {
+ return sendCommand("EXPIREAT", key, String.valueOf(unixTime))
+ .getIntegerReply();
+ }
+
+ public int ttl(String key) throws JedisException {
+ return sendCommand("TTL", key).getIntegerReply();
+ }
+
+ public String select(int index) throws JedisException {
+ return sendCommand("SELECT", String.valueOf(index))
+ .getStatusCodeReply();
+ }
+
+ public int move(String key, int dbIndex) throws JedisException {
+ return sendCommand("MOVE", key, String.valueOf(dbIndex))
+ .getIntegerReply();
+ }
+
+ public String flushAll() throws JedisException {
+ return sendCommand("FLUSHALL").getStatusCodeReply();
+ }
}
diff --git a/src/main/java/redis/clients/jedis/JedisException.java b/src/main/java/redis/clients/jedis/JedisException.java
new file mode 100644
index 0000000..e69cbac
--- /dev/null
+++ b/src/main/java/redis/clients/jedis/JedisException.java
@@ -0,0 +1,12 @@
+package redis.clients.jedis;
+
+public class JedisException extends Exception {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -2946266495682282677L;
+
+ public JedisException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/redis/clients/jedis/Protocol.java b/src/main/java/redis/clients/jedis/Protocol.java
index 8f00084..39c1ebe 100644
--- a/src/main/java/redis/clients/jedis/Protocol.java
+++ b/src/main/java/redis/clients/jedis/Protocol.java
@@ -10,6 +10,7 @@ public class Protocol {
public static final String DOLLAR = "$";
public static final String ASTERISK = "*";
public static final String PLUS = "+";
+ public static final String MINUS = "-";
public static final String COLON = ":";
public static final String COMMAND_DELIMITER = "\r\n";
public static final int DEFAULT_PORT = 6379;
@@ -17,6 +18,7 @@ public class Protocol {
public static final byte DOLLAR_BYTE = DOLLAR.getBytes()[0];
public static final byte ASTERISK_BYTE = ASTERISK.getBytes()[0];
public static final byte PLUS_BYTE = PLUS.getBytes()[0];
+ public static final byte MINUS_BYTE = MINUS.getBytes()[0];
public static final byte COLON_BYTE = COLON.getBytes()[0];
public void sendCommand(OutputStream os, String name, String... args) {
@@ -36,10 +38,40 @@ public class Protocol {
}
}
- public String getBulkReply(InputStream is) {
+ public void processError(InputStream is) throws JedisException {
+ String message = readLine(is);
+ throw new JedisException(message);
+ }
+
+ private String readLine(InputStream is) {
+ byte b;
+ StringBuilder sb = new StringBuilder();
+
+ try {
+ while ((b = (byte) is.read()) != -1) {
+ if (b == '\r') {
+ b = (byte) is.read();
+ if (b == '\n') {
+ break;
+ }
+ }
+ sb.append((char) b);
+ }
+ } catch (IOException e) {
+ // TODO Dont know what to do here!
+ }
+ return sb.toString();
+ }
+
+ public String getBulkReply(InputStream is) throws JedisException {
String ret = null;
try {
- if ((byte) is.read() == DOLLAR_BYTE) {
+ byte b = (byte) is.read();
+ if (b == MINUS_BYTE) {
+ processError(is);
+ }
+
+ if (b == DOLLAR_BYTE) {
int len = Integer.parseInt(readLine(is));
if (len == -1) {
return null;
@@ -60,26 +92,15 @@ public class Protocol {
return ret;
}
- private String readLine(InputStream is) throws IOException {
- byte b;
- StringBuilder sb = new StringBuilder();
-
- while ((b = (byte) is.read()) != -1) {
- if (b == '\r') {
- b = (byte) is.read();
- if (b == '\n') {
- break;
- }
- }
- sb.append((char) b);
- }
- return sb.toString();
- }
-
- public String getSingleLineReply(InputStream is) {
+ public String getSingleLineReply(InputStream is) throws JedisException {
String ret = null;
try {
- if ((byte) is.read() == PLUS_BYTE) {
+ byte b = (byte) is.read();
+ if (b == MINUS_BYTE) {
+ processError(is);
+ }
+
+ if (b == PLUS_BYTE) {
ret = readLine(is);
}
} catch (IOException e) {
@@ -89,24 +110,33 @@ public class Protocol {
return ret;
}
- public int getIntegerReply(InputStream is) {
+ public int getIntegerReply(InputStream is) throws JedisException {
int ret = 0;
try {
- if ((byte) is.read() == COLON_BYTE) {
+ byte b = (byte) is.read();
+ if (b == MINUS_BYTE) {
+ processError(is);
+ }
+ if (b == COLON_BYTE) {
String num = readLine(is);
ret = Integer.parseInt(num);
}
} catch (IOException e) {
// TODO Not sure that I should return 0
+ e.printStackTrace();
return 0;
}
return ret;
}
- public List getMultiBulkReply(InputStream is) {
+ public List getMultiBulkReply(InputStream is) throws JedisException {
List ret = new ArrayList();
try {
- if ((byte) is.read() == ASTERISK_BYTE) {
+ byte b = (byte) is.read();
+ if (b == MINUS_BYTE) {
+ processError(is);
+ }
+ if (b == ASTERISK_BYTE) {
int num = Integer.parseInt(readLine(is));
for (int i = 0; i < num; i++) {
ret.add(getBulkReply(is));
diff --git a/src/test/java/redis/clients/jedis/tests/ProtocolTest.java b/src/test/java/redis/clients/jedis/tests/ProtocolTest.java
index 5098fad..d0266f4 100644
--- a/src/test/java/redis/clients/jedis/tests/ProtocolTest.java
+++ b/src/test/java/redis/clients/jedis/tests/ProtocolTest.java
@@ -13,6 +13,7 @@ import junit.framework.Assert;
import org.junit.Test;
+import redis.clients.jedis.JedisException;
import redis.clients.jedis.Protocol;
public class ProtocolTest extends Assert {
@@ -38,7 +39,7 @@ public class ProtocolTest extends Assert {
}
@Test
- public void bulkReply() {
+ public void bulkReply() throws JedisException {
InputStream is = new ByteArrayInputStream("$6\r\nfoobar\r\n".getBytes());
Protocol protocol = new Protocol();
String response = protocol.getBulkReply(is);
@@ -46,7 +47,7 @@ public class ProtocolTest extends Assert {
}
@Test
- public void nullBulkReply() {
+ public void nullBulkReply() throws JedisException {
InputStream is = new ByteArrayInputStream("$-1\r\n".getBytes());
Protocol protocol = new Protocol();
String response = protocol.getBulkReply(is);
@@ -54,7 +55,7 @@ public class ProtocolTest extends Assert {
}
@Test
- public void singleLineReply() {
+ public void singleLineReply() throws JedisException {
InputStream is = new ByteArrayInputStream("+OK\r\n".getBytes());
Protocol protocol = new Protocol();
String response = protocol.getSingleLineReply(is);
@@ -62,7 +63,7 @@ public class ProtocolTest extends Assert {
}
@Test
- public void integerReply() {
+ public void integerReply() throws JedisException {
InputStream is = new ByteArrayInputStream(":123\r\n".getBytes());
Protocol protocol = new Protocol();
int response = protocol.getIntegerReply(is);
@@ -70,7 +71,7 @@ public class ProtocolTest extends Assert {
}
@Test
- public void multiBulkReply() {
+ public void multiBulkReply() throws JedisException {
InputStream is = new ByteArrayInputStream(
"*4\r\n$3\r\nfoo\r\n$3\r\nbar\r\n$5\r\nHello\r\n$5\r\nWorld\r\n"
.getBytes());
diff --git a/src/test/java/redis/clients/jedis/tests/commands/AllKindOfValuesCommandsTest.java b/src/test/java/redis/clients/jedis/tests/commands/AllKindOfValuesCommandsTest.java
new file mode 100644
index 0000000..283f776
--- /dev/null
+++ b/src/test/java/redis/clients/jedis/tests/commands/AllKindOfValuesCommandsTest.java
@@ -0,0 +1,248 @@
+package redis.clients.jedis.tests.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.Assert;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisException;
+
+public class AllKindOfValuesCommandsTest extends Assert {
+ private Jedis jedis;
+
+ @Before
+ public void setUp() throws Exception {
+ jedis = new Jedis("localhost");
+ jedis.connect();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ jedis.flushDB();
+ jedis.disconnect();
+ }
+
+ @Test
+ public void ping() throws JedisException {
+ String status = jedis.ping();
+ assertEquals("PONG", status);
+ }
+
+ @Test
+ public void exists() throws JedisException {
+ String status = jedis.set("foo", "bar");
+ assertEquals("OK", status);
+
+ int reply = jedis.exists("foo");
+ assertEquals(1, reply);
+
+ reply = jedis.del("foo");
+ assertEquals(1, reply);
+
+ reply = jedis.exists("foo");
+ assertEquals(0, reply);
+ }
+
+ @Test
+ public void del() throws JedisException {
+ jedis.set("foo1", "bar1");
+ jedis.set("foo2", "bar2");
+ jedis.set("foo3", "bar3");
+
+ int reply = jedis.del("foo1", "foo2", "foo3");
+ assertEquals(3, reply);
+
+ reply = jedis.exists("foo1");
+ assertEquals(0, reply);
+ reply = jedis.exists("foo2");
+ assertEquals(0, reply);
+ reply = jedis.exists("foo3");
+ assertEquals(0, reply);
+
+ jedis.set("foo1", "bar1");
+
+ reply = jedis.del("foo1", "foo2");
+ assertEquals(1, reply);
+
+ reply = jedis.del("foo1", "foo2");
+ assertEquals(0, reply);
+ }
+
+ @Test
+ public void type() throws JedisException {
+ jedis.set("foo", "bar");
+ String status = jedis.type("foo");
+ assertEquals("string", status);
+ }
+
+ @Test
+ public void keys() throws JedisException {
+ jedis.set("foo", "bar");
+ jedis.set("foobar", "bar");
+
+ List keys = jedis.keys("foo*");
+ List expected = new ArrayList();
+ expected.add("foo");
+ expected.add("foobar");
+ assertEquals(expected, keys);
+
+ expected = new ArrayList();
+ keys = jedis.keys("bar*");
+
+ assertEquals(expected, keys);
+ }
+
+ @Test
+ public void randomKey() throws JedisException {
+ assertEquals("", jedis.randomKey());
+
+ jedis.set("foo", "bar");
+
+ assertEquals("foo", jedis.randomKey());
+
+ jedis.set("bar", "foo");
+
+ String randomkey = jedis.randomKey();
+ assertTrue(randomkey.equals("foo") || randomkey.equals("bar"));
+ }
+
+ @Test
+ public void rename() throws JedisException {
+ jedis.set("foo", "bar");
+ String status = jedis.rename("foo", "bar");
+ assertEquals("OK", status);
+
+ String value = jedis.get("foo");
+ assertEquals(null, value);
+
+ value = jedis.get("bar");
+ assertEquals("bar", value);
+ }
+
+ @Test(expected = JedisException.class)
+ public void renameOldAndNewAreTheSame() throws JedisException {
+ jedis.set("foo", "bar");
+ jedis.rename("foo", "foo");
+ }
+
+ @Test
+ public void renamenx() throws JedisException {
+ jedis.set("foo", "bar");
+ int status = jedis.renamenx("foo", "bar");
+ assertEquals(1, status);
+
+ jedis.set("foo", "bar");
+ status = jedis.renamenx("foo", "bar");
+ assertEquals(0, status);
+ }
+
+ @Test
+ public void dbSize() throws JedisException {
+ int size = jedis.dbSize();
+ assertEquals(0, size);
+
+ jedis.set("foo", "bar");
+ size = jedis.dbSize();
+ assertEquals(1, size);
+ }
+
+ @Test
+ public void expire() throws JedisException {
+ int status = jedis.expire("foo", 20);
+ assertEquals(0, status);
+
+ jedis.set("foo", "bar");
+ status = jedis.expire("foo", 20);
+ assertEquals(1, status);
+
+ status = jedis.expire("foo", 20);
+ assertEquals(0, status);
+ }
+
+ @Test
+ public void expireAt() throws JedisException {
+ long unixTime = (System.currentTimeMillis() / 1000L) + 20;
+
+ int status = jedis.expireAt("foo", unixTime);
+ assertEquals(0, status);
+
+ jedis.set("foo", "bar");
+ unixTime = (System.currentTimeMillis() / 1000L) + 20;
+ status = jedis.expireAt("foo", unixTime);
+ assertEquals(1, status);
+
+ unixTime = (System.currentTimeMillis() / 1000L) + 20;
+ status = jedis.expireAt("foo", unixTime);
+ assertEquals(0, status);
+ }
+
+ @Test
+ public void ttl() throws JedisException {
+ int ttl = jedis.ttl("foo");
+ assertEquals(-1, ttl);
+
+ jedis.set("foo", "bar");
+ ttl = jedis.ttl("foo");
+ assertEquals(-1, ttl);
+
+ jedis.expire("foo", 20);
+ ttl = jedis.ttl("foo");
+ assertTrue(ttl >= 0 && ttl <= 20);
+ }
+
+ @Test
+ public void select() throws JedisException {
+ jedis.set("foo", "bar");
+ String status = jedis.select(1);
+ assertEquals("OK", status);
+ assertEquals(null, jedis.get("foo"));
+ status = jedis.select(0);
+ assertEquals("OK", status);
+ assertEquals("bar", jedis.get("foo"));
+ }
+
+ @Test
+ public void move() throws JedisException {
+ int status = jedis.move("foo", 1);
+ assertEquals(0, status);
+
+ jedis.set("foo", "bar");
+ status = jedis.move("foo", 1);
+ assertEquals(1, status);
+ assertEquals(null, jedis.get("foo"));
+
+ jedis.select(1);
+ assertEquals("bar", jedis.get("foo"));
+ }
+
+ @Test
+ public void flushDB() throws JedisException {
+ jedis.set("foo", "bar");
+ assertEquals(1, jedis.dbSize());
+ jedis.set("bar", "foo");
+ jedis.move("bar", 1);
+ String status = jedis.flushDB();
+ assertEquals("OK", status);
+ assertEquals(0, jedis.dbSize());
+ jedis.select(1);
+ assertEquals(1, jedis.dbSize());
+ }
+
+ @Test
+ public void flushAll() throws JedisException {
+ jedis.set("foo", "bar");
+ assertEquals(1, jedis.dbSize());
+ jedis.set("bar", "foo");
+ jedis.move("bar", 1);
+ String status = jedis.flushAll();
+ assertEquals("OK", status);
+ assertEquals(0, jedis.dbSize());
+ jedis.select(1);
+ assertEquals(0, jedis.dbSize());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/redis/clients/jedis/tests/commands/ConnectionHandlingCommandsTest.java b/src/test/java/redis/clients/jedis/tests/commands/ConnectionHandlingCommandsTest.java
new file mode 100644
index 0000000..4d41dbe
--- /dev/null
+++ b/src/test/java/redis/clients/jedis/tests/commands/ConnectionHandlingCommandsTest.java
@@ -0,0 +1,37 @@
+package redis.clients.jedis.tests.commands;
+
+import junit.framework.Assert;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import redis.clients.jedis.Jedis;
+
+public class ConnectionHandlingCommandsTest extends Assert {
+ private Jedis jedis;
+
+ @Before
+ public void setUp() throws Exception {
+ jedis = new Jedis("localhost");
+ jedis.connect();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ jedis.flushDB();
+ jedis.disconnect();
+ }
+
+ @Test
+ public void quit() {
+ jedis.quit();
+ }
+
+ @Test
+ @Ignore(value = "Need to implement!")
+ public void auth() {
+
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/redis/clients/jedis/tests/JedisTest.java b/src/test/java/redis/clients/jedis/tests/commands/StringValuesCommandsTest.java
similarity index 59%
rename from src/test/java/redis/clients/jedis/tests/JedisTest.java
rename to src/test/java/redis/clients/jedis/tests/commands/StringValuesCommandsTest.java
index b2793ea..1ad66fc 100644
--- a/src/test/java/redis/clients/jedis/tests/JedisTest.java
+++ b/src/test/java/redis/clients/jedis/tests/commands/StringValuesCommandsTest.java
@@ -1,7 +1,4 @@
-package redis.clients.jedis.tests;
-
-import java.io.IOException;
-import java.net.UnknownHostException;
+package redis.clients.jedis.tests.commands;
import junit.framework.Assert;
@@ -10,8 +7,9 @@ import org.junit.Before;
import org.junit.Test;
import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisException;
-public class JedisTest extends Assert {
+public class StringValuesCommandsTest extends Assert {
private Jedis jedis;
@Before
@@ -22,21 +20,17 @@ public class JedisTest extends Assert {
@After
public void tearDown() throws Exception {
+ jedis.flushDB();
jedis.disconnect();
}
@Test
- public void ping() throws UnknownHostException, IOException {
- String status = jedis.ping();
- assertEquals("PONG", status);
- }
-
- @Test
- public void setAndGet() throws UnknownHostException, IOException {
+ public void setAndGet() throws JedisException {
String status = jedis.set("foo", "bar");
assertEquals("OK", status);
String value = jedis.get("foo");
assertEquals("bar", value);
}
+
}