diff --git a/pom.xml b/pom.xml index c22844e4f5..30bd2c1bd2 100644 --- a/pom.xml +++ b/pom.xml @@ -294,14 +294,6 @@ provided - - - com.alibaba - fastjson - 1.1.19 - provided - - mysql mysql-connector-java diff --git a/src/main/java/com/alibaba/druid/pool/ha/cobar/CobarConfigLoader.java b/src/main/java/com/alibaba/druid/pool/ha/cobar/CobarConfigLoader.java index 6b3ab4b130..13750dba2c 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/cobar/CobarConfigLoader.java +++ b/src/main/java/com/alibaba/druid/pool/ha/cobar/CobarConfigLoader.java @@ -5,15 +5,14 @@ import java.net.URL; import java.sql.SQLException; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Set; import com.alibaba.druid.pool.ha.DataSourceHolder; import com.alibaba.druid.pool.ha.config.ConfigLoader; import com.alibaba.druid.pool.ha.config.URLConnectionConfigLoader; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; +import com.alibaba.druid.support.json.JSONUtils; public class CobarConfigLoader extends URLConnectionConfigLoader implements ConfigLoader { @@ -63,26 +62,27 @@ public class CobarConfigLoader extends URLConnectionConfigLoader implements Conf } } + @SuppressWarnings({ "rawtypes", "unchecked" }) @Override protected void handleResponseMessage() throws SQLException { String responseMessage = this.getResponseMessage(); - JSONObject json = JSON.parseObject(responseMessage); - String errorMessage = json.getString("error"); + Map json = (Map) JSONUtils.parse(responseMessage); + String errorMessage = (String) json.get("error"); if (errorMessage != null) { throw new SQLException("load config error, message : " + errorMessage); } - JSONArray array = json.getJSONArray("cobarList"); + List array = (List) json.get("cobarList"); Set keys = new HashSet(); for (int i = 0; i < array.size(); ++i) { - JSONObject item = array.getJSONObject(i); + Map item = (Map) array.get(i); - String ip = item.getString("ip"); - int port = item.getIntValue("port"); - String schema = item.getString("schema"); - int weight = item.getIntValue("weight"); + String ip = (String) item.get("ip"); + int port = (Integer) item.get("port"); + String schema = (String) item.get("schema"); + int weight = (Integer) item.get("weight"); String key = ip + ":" + port + "/" + schema; keys.add(key); diff --git a/src/main/java/com/alibaba/druid/pool/ha/config/HAConfigLoader.java b/src/main/java/com/alibaba/druid/pool/ha/config/HAConfigLoader.java index 1ca0b04a31..18af44893b 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/config/HAConfigLoader.java +++ b/src/main/java/com/alibaba/druid/pool/ha/config/HAConfigLoader.java @@ -2,10 +2,9 @@ package com.alibaba.druid.pool.ha.config; import java.net.URL; import java.sql.SQLException; +import java.util.Map; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; - +import com.alibaba.druid.support.json.JSONUtils; public class HAConfigLoader extends URLConnectionConfigLoader { @@ -15,8 +14,9 @@ public class HAConfigLoader extends URLConnectionConfigLoader { @Override protected void handleResponseMessage() throws SQLException { - JSONObject json = JSON.parseObject(this.getResponseMessage()); - json.get("serverList"); + @SuppressWarnings("unchecked") + Map map = (Map) JSONUtils.parse(this.getResponseMessage()); + map.get("serverList"); } } diff --git a/src/main/java/com/alibaba/druid/support/DruidStatJSONService.java b/src/main/java/com/alibaba/druid/support/DruidStatJSONService.java index ab79eb2ab0..cdf66d8d9f 100644 --- a/src/main/java/com/alibaba/druid/support/DruidStatJSONService.java +++ b/src/main/java/com/alibaba/druid/support/DruidStatJSONService.java @@ -13,10 +13,10 @@ import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.visitor.SchemaStatVisitor; import com.alibaba.druid.stat.DruidStatManagerFacade; import com.alibaba.druid.support.http.stat.WebAppStatManager; +import com.alibaba.druid.support.json.JSONUtils; import com.alibaba.druid.support.spring.stat.SpringStatManager; import com.alibaba.druid.util.MapComparator; import com.alibaba.druid.util.StringUtils; -import com.alibaba.fastjson.JSON; /** * 注意:避免直接调用Druid相关对象例如DruidDataSource等,相关调用要到DruidStatManagerFacade里用反射实现 @@ -246,7 +246,7 @@ public class DruidStatJSONService { Map dataMap = new LinkedHashMap(); dataMap.put("ResultCode", resultCode); dataMap.put("Content", content); - return JSON.toJSONStringWithDateFormat(dataMap, "yyyy-MM-dd HH:mm:ss"); + return JSONUtils.toJSONString(dataMap); } } diff --git a/src/main/java/com/alibaba/druid/support/json/JSONParser.java b/src/main/java/com/alibaba/druid/support/json/JSONParser.java new file mode 100644 index 0000000000..216ec505a3 --- /dev/null +++ b/src/main/java/com/alibaba/druid/support/json/JSONParser.java @@ -0,0 +1,329 @@ +package com.alibaba.druid.support.json; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class JSONParser { + + private String text; + private int index = 0; + private char ch; + + private Token token; + private String stringValue; + private long longValue; + private double doubleValue; + + public JSONParser(String text){ + this.text = text; + ch = text.charAt(0); + nextToken(); + } + + public Object parse() { + if (token == Token.LBRACE) { + return parseMap(); + } + + if (token == Token.INT) { + Object value; + if (this.longValue >= Integer.MIN_VALUE && this.longValue <= Integer.MAX_VALUE) { + value = (int) this.longValue; + } else { + value = this.longValue; + } + + nextToken(); + return value; + } + + if (token == Token.DOUBLE) { + Object value = this.doubleValue; + nextToken(); + return value; + } + + if (token == Token.STRING) { + Object value = this.stringValue; + nextToken(); + return value; + } + + if (token == Token.LBRACKET) { + return parseArray(); + } + + if (token == Token.TRUE) { + nextToken(); + return true; + } + + if (token == Token.FALSE) { + nextToken(); + return false; + } + + throw new IllegalArgumentException("illegal token : " + token); + } + + public List parseArray() { + accept(Token.LBRACKET); + ArrayList list = new ArrayList(); + + for (;;) { + if (token == Token.RBRACKET) { + break; + } + + if (token == Token.COMMA) { + nextToken(); + continue; + } + + Object item = parse(); + list.add(item); + } + + accept(Token.RBRACKET); + return list; + } + + public Map parseMap() { + accept(Token.LBRACE); + Map map = new LinkedHashMap(); + + for (;;) { + if (token == Token.RBRACE) { + break; + } + + if (token == Token.COMMA) { + nextToken(); + continue; + } + + String key; + { + if (token != Token.STRING) { + throw new IllegalArgumentException("illegal json, " + token + " : " + text); + } + key = this.stringValue; + nextToken(); + } + + accept(Token.COLON); + + Object value = parse(); + + map.put(key, value); + } + + accept(Token.RBRACE); + return map; + } + + void accept(Token token) { + if (this.token == token) { + nextToken(); + return; + } + + throw new IllegalArgumentException("illegal token : " + token + ", expect " + token); + } + + void nextToken() { + if (index == Integer.MIN_VALUE) { + token = Token.EOF; + return; + } + + for (;;) { + if (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t') { + nextChar(); + continue; + } + + if (index >= text.length()) { + token = Token.EOF; + return; + } + + break; + } + + switch (ch) { + case '{': + token = Token.LBRACE; + nextChar(); + break; + case '}': + token = Token.RBRACE; + nextChar(); + break; + case '[': + token = Token.LBRACKET; + nextChar(); + break; + case ']': + token = Token.RBRACKET; + nextChar(); + break; + case ',': + token = Token.COMMA; + nextChar(); + break; + case ':': + token = Token.COLON; + nextChar(); + break; + case '"': + scanString(); + break; + default: + if (isDigit(ch) || ch == '-') { + scanDigit(); + return; + } + + if (text.startsWith("true", index)) { + token = Token.TRUE; + index += 3; + nextChar(); + return; + } + + if (text.startsWith("false", index)) { + token = Token.FALSE; + index += 4; + nextChar(); + return; + } + throw new IllegalArgumentException("illegal json char : " + ch); + } + } + + private void scanDigit() { + boolean isNegate = false; + if (ch == '-') { + isNegate = true; + nextChar(); + } + + int dotCount = 0; + StringBuilder digitBuf = new StringBuilder(); + for (;;) { + digitBuf.append(ch); + nextChar(); + + if (ch == '.') { + dotCount++; + digitBuf.append('.'); + nextChar(); + continue; + } + + if (!isDigit(ch)) { + break; + } + } + + if (dotCount == 0) { + long longValue = Long.parseLong(digitBuf.toString()); + if (isNegate) { + longValue = -longValue; + } + this.longValue = longValue; + token = Token.INT; + } else { + double doubleValue = Double.parseDouble(digitBuf.toString()); + if (isNegate) { + doubleValue = -doubleValue; + } + this.doubleValue = doubleValue; + token = Token.DOUBLE; + } + } + + private void scanString() { + nextChar(); + StringBuilder strBuf = new StringBuilder(); + for (;;) { + if (index >= text.length()) { + throw new IllegalArgumentException("illegal string : " + strBuf); + } + if (ch == '"') { + nextChar(); + break; + } + + if (ch == '\\') { + nextChar(); + if (ch == '"' || ch == '\\' || ch == '/') { + strBuf.append(ch); + } else if (ch == 'n') { + strBuf.append('\n'); + } else if (ch == 'r') { + strBuf.append('\r'); + } else if (ch == 'b') { + strBuf.append('\b'); + } else if (ch == 'f') { + strBuf.append('\f'); + } else if (ch == 't') { + strBuf.append('\t'); + } else { + throw new IllegalArgumentException("illegal string : " + strBuf); + } + } else { + strBuf.append(ch); + } + nextChar(); + } + stringValue = strBuf.toString(); + token = Token.STRING; + } + + static boolean isDigit(char ch) { + return ch >= '0' && ch <= '9'; + } + + void nextChar() { + ++index; + if (index >= text.length()) { + index = Integer.MIN_VALUE; + return; + } + + ch = text.charAt(index); + } + + enum Token { + INT, // + DOUBLE, // + STRING, // + BOOLEAN, // + TRUE, // + FALSE, // + EOF, // + + LBRACE("{"), // + RBRACE("}"), // + LBRACKET("["), // + RBRACKET("]"), // + COMMA(","), // + COLON(":"), + + ; + + public final String name; + + Token(){ + this(null); + } + + Token(String name){ + this.name = name; + } + } +} diff --git a/src/main/java/com/alibaba/druid/support/json/JSONUtils.java b/src/main/java/com/alibaba/druid/support/json/JSONUtils.java new file mode 100644 index 0000000000..a3ff745842 --- /dev/null +++ b/src/main/java/com/alibaba/druid/support/json/JSONUtils.java @@ -0,0 +1,15 @@ +package com.alibaba.druid.support.json; + +public class JSONUtils { + + public static String toJSONString(Object o) { + JSONWriter writer = new JSONWriter(); + writer.writeObject(o); + return writer.toString(); + } + + public static Object parse(String text) { + JSONParser parser = new JSONParser(text); + return parser.parse(); + } +} diff --git a/src/main/java/com/alibaba/druid/support/json/JSONWriter.java b/src/main/java/com/alibaba/druid/support/json/JSONWriter.java new file mode 100644 index 0000000000..23ae09c746 --- /dev/null +++ b/src/main/java/com/alibaba/druid/support/json/JSONWriter.java @@ -0,0 +1,214 @@ +package com.alibaba.druid.support.json; + +import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.Date; +import java.util.Map; + +import com.alibaba.druid.util.IOUtils; + +public class JSONWriter { + + private StringBuilder out; + + private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + public JSONWriter(){ + this.out = new StringBuilder(); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void writeObject(Object o) { + if (o == null) { + write("null"); + return; + } + + if (o instanceof Map) { + writeMap((Map) o); + return; + } + + if (o instanceof Collection) { + writeArray((Collection) o); + return; + } + + if (o instanceof String) { + writeString((String) o); + return; + } + + if (o instanceof Number) { + write(o.toString()); + return; + } + + if (o instanceof Boolean) { + write(o.toString()); + return; + } + + if (o instanceof Date) { + writeDate((Date) o); + return; + } + + if (o instanceof Throwable) { + writeError((Throwable) o); + return; + } + + if (o instanceof int[]) { + int[] array = (int[]) o; + write('['); + for (int i = 0; i < array.length; ++i) { + if (i != 0) { + write(','); + } + write(array[i]); + } + write(']'); + return; + } + + if (o instanceof long[]) { + long[] array = (long[]) o; + write('['); + for (int i = 0; i < array.length; ++i) { + if (i != 0) { + write(','); + } + write(array[i]); + } + write(']'); + return; + } + + throw new IllegalArgumentException("not support type : " + o.getClass()); + } + + public void writeDate(Date date) { + if (date == null) { + write("null"); + return; + } + + writeString(dateFormat.format(date)); + } + + public void writeError(Throwable error) { + if (error == null) { + write("null"); + return; + } + + write("{\"Class\":"); + writeString(error.getClass().getName()); + write(",\"Message\":"); + writeString(error.getMessage()); + write(",\"StackTrace\":"); + writeString(IOUtils.getStackTrace(error)); + write('}'); + } + + public void writeArray(Object[] array) { + if (array == null) { + write("null"); + return; + } + + write('['); + + for (int i = 0; i < array.length; ++i) { + if (i != 0) { + write(','); + } + writeObject(array[i]); + } + + write(']'); + } + + public void writeArray(Collection list) { + if (list == null) { + write("null"); + return; + } + + int entryIndex = 0; + write('['); + + for (Object entry : list) { + if (entryIndex != 0) { + write(','); + } + writeObject(entry); + entryIndex++; + } + + write(']'); + } + + public void writeString(String text) { + write('"'); + for (int i = 0; i < text.length(); ++i) { + char c = text.charAt(i); + if (c == '"') { + write("\\\""); + } else if (c == '\n') { + write("\\n"); + } else if (c == '\r') { + write("\\r"); + } else if (c == '\\') { + write("\\\\"); + } else { + write(c); + } + } + write('"'); + } + + public void writeMap(Map map) { + if (map == null) { + write("null"); + return; + } + + int entryIndex = 0; + write('{'); + for (Map.Entry entry : map.entrySet()) { + if (entryIndex != 0) { + write(','); + } + + writeString(entry.getKey()); + write(':'); + writeObject(entry.getValue()); + + entryIndex++; + } + + write('}'); + } + + protected void write(String text) { + out.append(text); + } + + protected void write(char c) { + out.append(c); + } + + protected void write(int c) { + out.append(c); + } + + protected void write(long c) { + out.append(c); + } + + public String toString() { + return out.toString(); + } +} diff --git a/src/main/java/com/alibaba/druid/util/StringUtils.java b/src/main/java/com/alibaba/druid/util/StringUtils.java index 38a79edd7d..36596e3cbd 100644 --- a/src/main/java/com/alibaba/druid/util/StringUtils.java +++ b/src/main/java/com/alibaba/druid/util/StringUtils.java @@ -9,7 +9,6 @@ import java.util.StringTokenizer; import com.alibaba.druid.support.logging.Log; import com.alibaba.druid.support.logging.LogFactory; -import com.alibaba.fastjson.JSON; /** * @author sandzhang @@ -180,10 +179,6 @@ public class StringUtils { return (String[]) collection.toArray(new String[collection.size()]); } - public static void main(String args[]) { - System.out.println(JSON.toJSONString(getParameters("test?t=1&f=").get("t"))); - } - public static boolean equals(String a, String b) { if (a == null) { return b == null; diff --git a/src/test/java/com/alibaba/druid/bvt/support/json/JSONParserTest.java b/src/test/java/com/alibaba/druid/bvt/support/json/JSONParserTest.java new file mode 100644 index 0000000000..0183d42b87 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/support/json/JSONParserTest.java @@ -0,0 +1,29 @@ +package com.alibaba.druid.bvt.support.json; + +import java.util.List; +import java.util.Map; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.support.json.JSONParser; + +public class JSONParserTest extends TestCase { + + public void test_parse() throws Exception { + JSONParser parser = new JSONParser("{ \"id\":33,\"name\":\"jobs\",\"values\":[1,2,3,4], \"f1\":true, \"f2\":false,\"f3\":-234,\"f4\":3.5}"); + Map map = (Map) parser.parse(); + Assert.assertEquals(33, map.get("id")); + Assert.assertEquals("jobs", map.get("name")); + Assert.assertEquals(4, ((List) map.get("values")).size()); + Assert.assertEquals(1, ((List) map.get("values")).get(0)); + Assert.assertEquals(2, ((List) map.get("values")).get(1)); + Assert.assertEquals(3, ((List) map.get("values")).get(2)); + Assert.assertEquals(4, ((List) map.get("values")).get(3)); + Assert.assertEquals(true, map.get("f1")); + Assert.assertEquals(false, map.get("f2")); + Assert.assertEquals(-234, map.get("f3")); + Assert.assertEquals(3.5D, map.get("f4")); + } +}