diff --git a/src/zutil/db/MySQLConnection.java b/src/zutil/db/MySQLConnection.java new file mode 100644 index 0000000..e5f9885 --- /dev/null +++ b/src/zutil/db/MySQLConnection.java @@ -0,0 +1,108 @@ +package zutil.db; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +public class MySQLConnection { + Connection conn = null; + + /** + * Connects to a MySQL server + * + * @param url is the URL of the MySQL server + * @param db is the database to connect to + * @param user is the user name + * @param password is the password + */ + public MySQLConnection(String url, String db, String user, String password) + throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException{ + Class.forName ("com.mysql.jdbc.Driver").newInstance(); + DriverManager.setLoginTimeout(10); + conn = DriverManager.getConnection ("jdbc:mysql://"+url+"/"+db, user, password); + } + + /** + * Runs a query and returns the result.
+ * NOTE: Don't forget to close the ResultSet and the Statement or it + * can lead to memory leak: rows.getStatement().close(); + * + * @param sql is the query to execute + * @return the data that the DB returned + */ + public synchronized ResultSet query(String sql) throws SQLException{ + Statement s = conn.createStatement (); + s.executeQuery(sql); + return s.getResultSet(); + } + + /** + * Returns the first cell of the first row of the query + * + * @param sql is the SQL query to run, preferably with the LIMIT 1 at the end + * @return A SQL row if it exists or else null + */ + public synchronized String simpleQuery(String sql) throws SQLException{ + Statement s = conn.createStatement (); + s.executeQuery(sql); + ResultSet result = s.getResultSet(); + if(result.next()){ + String tmp = result.getString(1); + result.close(); + return tmp; + } + return null; + } + + /** + * Runs a query in the MySQL server and returns effected rows + * + * @param sql is the query to execute + * @return the number of rows effected + */ + public synchronized int updateQuery(String sql) throws SQLException{ + Statement s = conn.createStatement (); + int ret = s.executeUpdate(sql); + s.close(); + return ret; + } + + /** + * @return the last inserted id or -1 if there was an error + * @throws SQLException + */ + public int getLastInsertID() throws SQLException{ + Statement s = conn.createStatement (); + s.executeQuery("SELECT LAST_INSERT_ID()"); + ResultSet result = s.getResultSet(); + if(result.next()){ + int tmp = result.getInt(1); + result.close(); + return tmp; + } + return -1; + } + + /** + * Runs a Prepared Statement.
+ * NOTE: Don't forget to close the PreparedStatement or it can lead to memory leak + * + * @param sql is the SQL query to run + * @return The PreparedStatement + */ + public synchronized PreparedStatement prepareStatement(String sql) throws SQLException{ + return conn.prepareStatement(sql); + } + + /** + * Disconnects from the database + */ + public synchronized void close() throws SQLException{ + if (conn != null){ + conn.close (); + } + } +} diff --git a/src/zutil/db/MySQLQueue.java b/src/zutil/db/MySQLQueue.java new file mode 100644 index 0000000..7ca1bf8 --- /dev/null +++ b/src/zutil/db/MySQLQueue.java @@ -0,0 +1,181 @@ +package zutil.db; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collection; +import java.util.Iterator; +import java.util.Queue; + +import zutil.MultiPrintStream; +import zutil.converters.Converter; + +/** + * This class creates a queue that stors the + * data in a mysql table. + * The table should look like this: + * CREATE TABLE `queue` ( + * `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY , + * `data` BINARY NOT NULL + * ); + * @author Ziver + * + */ +public class MySQLQueue implements Queue{ + // GO TO KNOW = SELECT LAST_INSERT_ID() as pos_id + private MySQLConnection db; + private String table; + + /** + * Initiats the queue. + * WARNING!! this will erase all rows i the table + * @param db The connection to the db + * @param table The name of the table + * @throws SQLException + */ + public MySQLQueue(MySQLConnection db, String table){ + this.db = db; + this.table = table; + } + + public boolean add(Object arg0){ + try { + PreparedStatement sql = db.prepareStatement("INSERT INTO "+table+" (data) VALUES(?)"); + sql.setObject(1, arg0); + sql.executeUpdate(); + sql.close(); + } catch (Exception e) { + e.printStackTrace(MultiPrintStream.out); + return false; + } + return true; + } + + public E element() { + return peek(); + } + + public boolean offer(Object arg0) { + // TODO Auto-generated method stub + return false; + } + + @SuppressWarnings("unchecked") + public synchronized E peek() { + try { + ResultSet rs = db.query("SELECT * FROM "+table+" LIMIT 1"); + if (rs.next()) { + return (E) Converter.toObject(rs.getBytes("data")); + } + rs.getStatement().close(); + } catch (Exception e) { + e.printStackTrace(MultiPrintStream.out); + } + return null; + } + + @SuppressWarnings("unchecked") + public synchronized E poll() { + try { + ResultSet rs = db.query("SELECT * FROM "+table+" LIMIT 1"); + if (rs.next()) { + db.updateQuery("DELETE FROM "+table+" WHERE id="+rs.getInt("id")+" LIMIT 1"); + return (E) Converter.toObject(rs.getBytes("data")); + } + rs.getStatement().close(); + } catch (Exception e) { + e.printStackTrace(MultiPrintStream.out); + } + return null; + } + + public E remove() { + return poll(); + } + + public boolean addAll(Collection arg0) { + // TODO Auto-generated method stub + return false; + } + + public void clear() { + try { + db.updateQuery("TRUNCATE TABLE `"+table+"`"); + } catch (SQLException e) { + e.printStackTrace(MultiPrintStream.out); + } + } + + public boolean contains(Object arg0) { + try { + ResultSet rs = db.query("SELECT data FROM "+table+" WHERE data='"+Converter.toBytes(arg0)+"' LIMIT 1"); + if (rs.next()) { + return true; + } + rs.getStatement().close(); + } catch (Exception e) { + e.printStackTrace(MultiPrintStream.out); + } + return false; + } + + public boolean containsAll(Collection arg0) { + // TODO Auto-generated method stub + return false; + } + + public boolean isEmpty() { + return (peek() != null); + } + + public Iterator iterator() { + // TODO Auto-generated method stub + return null; + } + + public synchronized boolean remove(Object arg0) { + try { + ResultSet rs = db.query("DELETE FROM "+table+" WHERE data='"+Converter.toBytes(arg0)+"' LIMIT 1"); + rs.getStatement().close(); + return true; + } catch (Exception e) { + e.printStackTrace(MultiPrintStream.out); + } + return false; + } + + public synchronized boolean removeAll(Collection arg0) { + // TODO Auto-generated method stub + return false; + } + + public boolean retainAll(Collection arg0) { + // TODO Auto-generated method stub + return false; + } + + public int size() { + try { + ResultSet rs = db.query("SELECT count(*) FROM "+table); + if (rs.next()) { + return rs.getInt(1); + } + rs.getStatement().close(); + } catch (Exception e) { + e.printStackTrace(MultiPrintStream.out); + } + return 0; + } + + public E[] toArray() { + // TODO Auto-generated method stub + return null; + } + + @SuppressWarnings("unchecked") + public E[] toArray(Object[] arg0) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/src/zutil/math/parser/MathParser.java b/src/zutil/parser/MathParser.java similarity index 95% rename from src/zutil/math/parser/MathParser.java rename to src/zutil/parser/MathParser.java index 052c9ef..3a5903e 100644 --- a/src/zutil/math/parser/MathParser.java +++ b/src/zutil/parser/MathParser.java @@ -1,4 +1,4 @@ -package zutil.math.parser; +package zutil.parser; import java.io.BufferedReader; import java.io.IOException; diff --git a/src/zutil/parser/json/JSONNode.java b/src/zutil/parser/json/JSONNode.java new file mode 100644 index 0000000..d032380 --- /dev/null +++ b/src/zutil/parser/json/JSONNode.java @@ -0,0 +1,247 @@ +package zutil.parser.json; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + + +/** + * This is an node in an JSON tree, + * it may contain a Map, list or value + * + * @author Ziver + */ +public class JSONNode implements Iterable{ + public enum JSONType{ + Map, List, String, Number, Boolean + } + private Map map = null; + private List list = null; + private String value = null; + private JSONType type; + + + /** + * Creates an instance with an Boolean value + */ + public JSONNode(boolean value){ + this.type = JSONType.Boolean; + this.value = ""+value; + } + /** + * Creates an instance with an int value + */ + public JSONNode(int value){ + this.type = JSONType.Number; + this.value = ""+value; + } + /** + * Creates an instance with an double value + */ + public JSONNode(double value){ + this.type = JSONType.Number; + this.value = ""+value; + } + /** + * Creates an instance with an String value + */ + public JSONNode(String value){ + this.type = JSONType.String; + this.value = value; + } + /** + * Creates an instance with a specific type + */ + public JSONNode(JSONType type){ + this.type = type; + switch(type){ + case Map: + map = new HashMap(); break; + case List: + list = new LinkedList(); break; + } + } + + /** + * @param index is the index of the List or Map + * @return an JSONNode that contains the next level of the List or Map + */ + public JSONNode get(int index){ + if(map != null) + return map.get(""+index); + else if(list != null) + return list.get(index); + return null; + } + /** + * @param index is the key in the Map + * @return an JSONNode that contains the next level of the Map + */ + public JSONNode get(String index){ + if(map != null) + return map.get(index); + return null; + } + + /** + * @return a iterator for the Map or List or null if the node contains a value + */ + public Iterator iterator(){ + if(map != null) + return map.values().iterator(); + else if(list != null) + return list.iterator(); + return null; + } + /** + * @return a iterator for the keys in the Map or null if the node contains a value or List + */ + public Iterator keyIterator(){ + if(map != null) + return map.keySet().iterator(); + return null; + } + /** + * @return the size of the Map or List or -1 if it is a value + */ + public int size(){ + if(map != null) + return map.size(); + else if(list != null) + return list.size(); + return -1; + } + + + /** + * Adds a node to the List + */ + public void add(JSONNode node){ + list.add(node); + } + public void add(boolean value){ + list.add(new JSONNode( value )); + } + public void add(int value){ + list.add(new JSONNode( value )); + } + public void add(double value){ + list.add(new JSONNode( value )); + } + public void add(String value){ + list.add(new JSONNode( value )); + } + /** + * Adds a node to the Map + */ + public void add(String key, JSONNode node){ + map.put(key, node); + } + public void add(String key, boolean value){ + map.put(key, new JSONNode(value)); + } + public void add(String key, int value){ + map.put(key, new JSONNode(value)); + } + public void add(String key, double value){ + map.put(key, new JSONNode(value)); + } + public void add(String key, String value){ + map.put(key, new JSONNode(value)); + } + /** + * Sets the value of the node, but only if it is setup as an JSONType.Value + */ + public void set(int value){ + if( !this.isValue() ) return; + type = JSONType.Number; + this.value = ""+value; + } + /** + * Sets the value of the node, but only if it is setup as an JSONType.Value + */ + public void set(double value){ + if( !this.isValue() ) return; + type = JSONType.Number; + this.value = ""+value; + } + /** + * Sets the value of the node, but only if it is setup as an JSONType.Value + */ + public void set(boolean value){ + if( !this.isValue() ) return; + type = JSONType.Boolean; + this.value = ""+value; + } + /** + * Sets the value of the node, but only if it is setup as an JSONType.Value + */ + public void set(String value){ + if( !this.isValue() ) return; + type = JSONType.String; + this.value = value; + } + + + /** + * @return if this node contains an Map + */ + public boolean isMap(){ + return type == JSONType.Map; + } + /** + * @return if this node contains an List + */ + public boolean isList(){ + return type == JSONType.List; + } + /** + * @return if this node contains an value + */ + public boolean isValue(){ + return type != JSONType.Map && type != JSONType.List; + } + /** + * @return the type of the node + */ + public JSONType getType(){ + return type; + } + + + /** + * @return the String value in this node, null if its a Map or List + */ + public String getString(){ + return value; + } + /** + * @return the boolean value in this node + */ + public boolean getBoolean(){ + return Boolean.parseBoolean(value); + } + /** + * @return the integer value in this node + */ + public int getInt(){ + return Integer.parseInt(value); + } + /** + * @return the double value in this node + */ + public double getDouble(){ + return Double.parseDouble(value); + } + + + public String toString(){ + if( this.isMap() ) + return map.toString(); + else if( this.isList() ) + return list.toString(); + return value; + } +} diff --git a/src/zutil/parser/json/JSONParser.java b/src/zutil/parser/json/JSONParser.java new file mode 100644 index 0000000..c15f765 --- /dev/null +++ b/src/zutil/parser/json/JSONParser.java @@ -0,0 +1,162 @@ +package zutil.parser.json; + +import zutil.MultiPrintStream; +import zutil.parser.json.JSONNode.JSONType; + +public class JSONParser { + private String json; + private int index; + + + public static void main(String[] args){ + JSONParser parser = new JSONParser("" + + "{"+ + " \"firstName\": \"John\","+ + " \"lastName\": \"Smith\","+ + " \"age\": 25,"+ + " \"address\": {"+ + " \"streetAddress\": \"21 2nd Street\","+ + " \"city\": \"New York\","+ + " \"state\": \"NY\","+ + " \"postalCode\": \"10021\""+ + " },"+ + " \"phoneNumber\": ["+ + " { \"type\": \"home\", \"number\": \"212 555-1234\" },"+ + " { \"type\": \"fax\", \"number\": \"646 555-4567\" }"+ + " ]"+ + "}"); + JSONNode node = parser.read(); + MultiPrintStream.out.dump( node ); + JSONWriter writer = new JSONWriter(System.out); + writer.write(node); + } + + public JSONParser(String json){ + this.json = json; + } + + public JSONNode read(){ + index = 0; + return parse(new StringBuffer(json)); + } + + protected JSONNode parse(StringBuffer json){ + JSONNode root = null; + JSONNode key = null; + JSONNode node = null; + int next_index; + + while(Character.isWhitespace( json.charAt(0) ) || + json.charAt(0) == ',' || json.charAt(0) == ':') + json.deleteCharAt(0); + char c = json.charAt(0); + json.deleteCharAt(0); + + switch( c ){ + case ']': + case '}': + return null; + case '{': + root = new JSONNode(JSONType.Map); + while((key = parse( json )) != null && (node = parse( json )) != null){ + root.add( key.toString(), node ); + } + break; + case '[': + root = new JSONNode(JSONType.List); + while((node = parse( json )) != null){ + root.add( node ); + } + break; + // Parse String + case '\"': + root = new JSONNode(JSONType.String); + next_index = json.indexOf("\""); + root.set( json.substring(0, next_index) ); + json.delete(0, next_index+1); + break; + default: + root = new JSONNode(JSONType.Number); + for(next_index=0; next_index it = root.keyIterator(); + while(it.hasNext()){ + if(!first) + out.print(", "); + String key = it.next(); + try{ + out.print( Integer.parseInt(key) ); + }catch(Exception e){ + out.print('\"'); + out.print(key); + out.print('\"'); + } + out.print(": "); + write( root.get(key) ); + first = false; + } + out.print('}'); + break; + // Write an list + case List: + out.print('['); + for(JSONNode node : root){ + if(!first) + out.print(", "); + write( node ); + first = false; + } + out.print(']'); + break; + default: + if(root.getType() == JSONType.String){ + out.print('\"'); + out.print(root.toString()); + out.print('\"'); + } else + out.print(root.toString()); + break; + } + out.flush(); + } + + /** + * Closes the internal stream + */ + public void close(){ + out.close(); + } + +}