Introduction of XSQL
[controller.git] / opendaylight / md-sal / sal-dom-xsql / src / main / java / org / opendaylight / controller / md / sal / dom / xsql / jdbc / JDBCServer.java
1 package org.opendaylight.controller.md.sal.dom.xsql.jdbc;
2
3 import org.opendaylight.controller.md.sal.dom.xsql.XSQLAdapter;
4 import org.opendaylight.controller.md.sal.dom.xsql.XSQLBluePrint;
5 import org.opendaylight.controller.md.sal.dom.xsql.XSQLBluePrintNode;
6 import org.opendaylight.controller.md.sal.dom.xsql.XSQLColumn;
7 import org.opendaylight.controller.md.sal.dom.xsql.XSQLCriteria;
8
9 import java.net.ServerSocket;
10 import java.net.Socket;
11 import java.sql.SQLException;
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.StringTokenizer;
16 import java.util.concurrent.ConcurrentHashMap;
17
18 public class JDBCServer extends Thread {
19     private ServerSocket socket = null;
20     private XSQLAdapter adapter = null;
21
22     public JDBCServer(XSQLAdapter a) {
23         super("JDBC Server");
24         this.adapter = a;
25         start();
26     }
27
28     public void run() {
29         try {
30             socket = new ServerSocket(40004);
31             while (!adapter.stopped) {
32                 Socket s = socket.accept();
33                 new JDBCConnection(s, adapter);
34             }
35         } catch (Exception err) {
36             err.printStackTrace();
37         }
38     }
39
40     public void connectToClient(String addr) {
41         try {
42             Socket s = new Socket(addr, 50003);
43             new JDBCConnection(s, adapter);
44         } catch (Exception err) {
45             err.printStackTrace();
46         }
47     }
48
49     public static void execute(JDBCResultSet rs, XSQLAdapter adapter)
50         throws SQLException {
51         parseTables(rs, adapter.getBluePrint());
52         parseFields(rs, adapter.getBluePrint());
53         parseCriteria(rs, adapter.getBluePrint());
54         try {
55             adapter.execute(rs);
56         } catch (Exception err) {
57             throw new SQLException("Error", err);
58         }
59     }
60
61     public static void parseTables(JDBCResultSet rs, XSQLBluePrint bp)
62         throws SQLException {
63         String lowSQL = rs.getSQL().toLowerCase();
64         int from = lowSQL.indexOf("from");
65         int where = lowSQL.indexOf("where");
66         int subQuery = lowSQL.indexOf("select", 2);
67         int fromTo = lowSQL.indexOf(";");
68
69         if (where != -1 && subQuery != -1 && where < subQuery) {
70             fromTo = where;
71         } else if (where != -1 && subQuery != -1 && where > subQuery) {
72             fromTo = subQuery;
73         } else if (where != -1) {
74             fromTo = where;
75         } else if (subQuery != -1) {
76             fromTo = subQuery;
77         }
78
79         if (from == -1) {
80             throw new SQLException("Missing \"from\" statement.");
81         }
82
83         if (fromTo == -1) {
84             throw new SQLException("Missing terminating \";\".");
85         }
86
87         String tableNames = rs.getSQL().substring(from + 4, fromTo).trim();
88         StringTokenizer tokens = new StringTokenizer(tableNames, ",");
89         while (tokens.hasMoreTokens()) {
90             String tableName = tokens.nextToken().trim();
91             XSQLBluePrintNode table = bp.getBluePrintNodeByTableName(tableName);
92             if (table == null) {
93                 throw new SQLException(
94                     "Unknown table name \"" + tableName + "\"");
95             }
96             rs.addTableToQuery(table);
97         }
98     }
99
100     public static void addCriteria(XSQLColumn col, XSQLCriteria c,
101         JDBCResultSet rs) {
102         Map<XSQLColumn, List<XSQLCriteria>> tblCriteria =
103             rs.getCriteria().get(col.getTableName());
104         if (tblCriteria == null) {
105             tblCriteria =
106                 new ConcurrentHashMap<XSQLColumn, List<XSQLCriteria>>();
107             rs.getCriteria().put(col.getTableName(), tblCriteria);
108         }
109         List<XSQLCriteria> lstCriteria = tblCriteria.get(col);
110         if (lstCriteria == null) {
111             lstCriteria = new ArrayList<XSQLCriteria>();
112             tblCriteria.put(col, lstCriteria);
113         }
114         lstCriteria.add(c);
115     }
116
117     public static void parseFields(JDBCResultSet rs, XSQLBluePrint bp)
118         throws SQLException {
119         String lowSQL = rs.getSQL().toLowerCase();
120         if (!lowSQL.startsWith("select")) {
121             throw new SQLException("Missing 'select' statement.");
122         }
123         int from = lowSQL.indexOf("from");
124         if (from == -1) {
125             throw new SQLException("Missing 'from' statement.");
126         }
127         String fields = rs.getSQL().substring(6, from).trim();
128         StringTokenizer tokens = new StringTokenizer(fields, ",");
129         while (tokens.hasMoreTokens()) {
130             String token = tokens.nextToken().trim();
131             if (token.equals("*")) {
132                 for (XSQLBluePrintNode table : rs.getTables()) {
133                     rs.getFields().addAll(table.getColumns());
134                 }
135                 return;
136             }
137             if (token.indexOf(".") != -1) {
138                 XSQLBluePrintNode tbl = bp.getBluePrintNodeByTableName(
139                     token.substring(0, token.indexOf(".")).trim());
140                 String p = token.substring(token.indexOf(".") + 1);
141                 if (p.equals("*")) {
142                     for (XSQLColumn c : tbl.getColumns()) {
143                         rs.getFields().add(c);
144                     }
145                 } else {
146                     XSQLColumn col = tbl.findColumnByName(p);
147                     rs.getFields().add(col);
148                 }
149             } else {
150                 XSQLColumn col = null;
151                 for (XSQLBluePrintNode table : rs.getTables()) {
152                     try {
153                         col = table.findColumnByName(token);
154                     } catch (Exception err) {
155                     }
156                     if (col != null) {
157                         break;
158                     }
159                 }
160                 if (col == null) {
161                     throw new SQLException(
162                         "Unknown field name '" + token + "'.");
163                 }
164
165                 rs.getFields().add(col);
166             }
167         }
168     }
169
170     public static void parseCriteria(JDBCResultSet rs, XSQLBluePrint bp) {
171         String lowSQL = rs.getSQL().toLowerCase();
172         int where = lowSQL.indexOf("where");
173         int order = lowSQL.indexOf("order");
174         int subQuery = lowSQL.indexOf("select", 2);
175         int whereTo = lowSQL.indexOf(";");
176
177         if (where == -1) {
178             return;
179         }
180
181         if (where != -1 && subQuery != -1 && subQuery < where) {
182             return;
183         }
184
185         if (order != -1 && subQuery != -1 && order < subQuery) {
186             whereTo = order;
187         } else if (order != -1 && subQuery != -1 && order > subQuery) {
188             whereTo = subQuery;
189         } else if (order != -1) {
190             whereTo = order;
191         } else if (subQuery != -1) {
192             whereTo = subQuery;
193         }
194         String whereStatement =
195             rs.getSQL().substring(where + 5, whereTo).trim();
196         XSQLCriteria cr = new XSQLCriteria(whereStatement, -1);
197         for (XSQLBluePrintNode tbl : rs.getTables()) {
198             for (XSQLColumn col : tbl.getColumns()) {
199                 String colCriteria = cr.getCriteriaForProperty(col);
200                 if (colCriteria != null && !colCriteria.trim().equals("")) {
201                     addCriteria(col, new XSQLCriteria(colCriteria, -1), rs);
202                 }
203             }
204         }
205     }
206 }