a6b5ca60638a803432839425706337e1c4726c56
[controller.git] / opendaylight / md-sal / sal-dom-xsql / src / main / java / org / opendaylight / controller / md / sal / dom / xsql / jdbc / JDBCConnection.java
1 /*
2  * Copyright (c) 2014, 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.controller.md.sal.dom.xsql.jdbc;
10
11 import java.io.BufferedInputStream;
12 import java.io.BufferedOutputStream;
13 import java.io.ByteArrayInputStream;
14 import java.io.ByteArrayOutputStream;
15 import java.io.DataInputStream;
16 import java.io.DataOutputStream;
17 import java.io.ObjectInputStream;
18 import java.io.ObjectOutputStream;
19 import java.net.ServerSocket;
20 import java.net.Socket;
21 import java.sql.Array;
22 import java.sql.Blob;
23 import java.sql.CallableStatement;
24 import java.sql.Clob;
25 import java.sql.Connection;
26 import java.sql.DatabaseMetaData;
27 import java.sql.NClob;
28 import java.sql.PreparedStatement;
29 import java.sql.SQLClientInfoException;
30 import java.sql.SQLException;
31 import java.sql.SQLWarning;
32 import java.sql.SQLXML;
33 import java.sql.Savepoint;
34 import java.sql.Statement;
35 import java.sql.Struct;
36 import java.util.LinkedList;
37 import java.util.Map;
38 import java.util.Properties;
39 import java.util.concurrent.Executor;
40
41 import org.opendaylight.controller.md.sal.dom.xsql.XSQLAdapter;
42 import org.opendaylight.controller.md.sal.dom.xsql.XSQLBluePrint;
43
44 public class JDBCConnection implements Connection, Runnable {
45     private Socket socket = null;
46     private DataInputStream in = null;
47     private DataOutputStream out = null;
48     private LinkedList<byte[]> queue = new LinkedList<byte[]>();
49     private XSQLAdapter adapter = null;
50     private XSQLBluePrint metaData = null;
51     private String addr = null;
52     private boolean wasClosed = false;
53
54     public JDBCConnection(Socket s, XSQLAdapter _a) {
55         this.socket = s;
56         this.adapter = _a;
57         try {
58             in = new DataInputStream(
59                     new BufferedInputStream(s.getInputStream()));
60             out = new DataOutputStream(new BufferedOutputStream(
61                     s.getOutputStream()));
62             new JDBCObjectReader();
63             new Thread(this).start();
64         } catch (Exception err) {
65             err.printStackTrace();
66         }
67     }
68
69     public Connection getProxy() {
70         return this;
71         /*
72         return (Connection) Proxy.newProxyInstance(this.getClass()
73                 .getClassLoader(), new Class[] { Connection.class },
74                 new JDBCProxy(this));
75                 */
76     }
77
78     public JDBCConnection(String _addr) throws Exception {
79         this.addr = _addr;
80         init();
81     }
82
83     private void init() throws Exception {
84         if (addr.startsWith("http://")) {
85             addr = addr.substring(7);
86         }
87         System.err.print("Address is:" + addr);
88         socket = new Socket(addr, 40004);
89         try {
90             in = new DataInputStream(new BufferedInputStream(
91                     socket.getInputStream()));
92             out = new DataOutputStream(new BufferedOutputStream(
93                     socket.getOutputStream()));
94             new JDBCObjectReader();
95             new Thread(this).start();
96         } catch (Exception err) {
97             err.printStackTrace();
98         }
99     }
100
101     public JDBCConnection(boolean server) {
102         try {
103             try (ServerSocket s = new ServerSocket(50003)) {
104                 socket = s.accept();
105                 try {
106                     in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
107                     out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
108                     new JDBCObjectReader();
109                     new Thread(this).start();
110                 } catch (Exception err) {
111                     err.printStackTrace();
112                 }
113             }
114         } catch (Exception err) {
115             err.printStackTrace();
116         }
117     }
118
119     private boolean isStopped() {
120         if (adapter != null && adapter.stopped) {
121             return true;
122         }
123         if (socket == null || socket.isClosed()) {
124             return true;
125         }
126         return false;
127     }
128
129     public void run() {
130         byte data[] = null;
131         while (!isStopped()) {
132             try {
133                 int len = in.readInt();
134                 data = new byte[len];
135                 in.readFully(data);
136                 addObject(data);
137
138             } catch (Exception err) {
139                 System.out.println("Connection Lost or Closed.");
140                 try {
141                     out.close();
142                 } catch (Exception er) {
143                 }
144                 out = null;
145                 try {
146                     in.close();
147                 } catch (Exception er) {
148                 }
149                 in = null;
150                 try {
151                     socket.close();
152                 } catch (Exception err2) {
153                 }
154                 socket = null;
155             }
156         }
157     }
158
159     private void addObject(byte[] data) {
160         synchronized (queue) {
161             queue.add(data);
162             queue.notifyAll();
163         }
164     }
165
166     private class JDBCObjectReader extends Thread {
167
168         public JDBCObjectReader() {
169             super("JDBCObjectReader");
170             start();
171         }
172
173         public void run() {
174             while (!isStopped()) {
175                 byte data[] = null;
176                 synchronized (queue) {
177                     if (queue.size() == 0) {
178                         try {
179                             queue.wait(1000);
180                         } catch (Exception err) {
181                         }
182                     }
183                     if (queue.size() > 0) {
184                         data = queue.removeFirst();
185                     }
186                 }
187                 if (data != null) {
188                     JDBCCommand command = (JDBCCommand) deSerialize(data);
189                     processCommand(command);
190                 }
191             }
192         }
193
194         private Object deSerialize(byte data[]) {
195             try {
196                 ByteArrayInputStream in = new ByteArrayInputStream(data);
197                 ObjectInputStream oin = new ObjectInputStream(in);
198                 return oin.readObject();
199             } catch (Exception err) {
200                 err.printStackTrace();
201             }
202             return null;
203         }
204     }
205
206     public void processCommand(JDBCCommand cmd) {
207         switch (cmd.getType()) {
208         case JDBCCommand.TYPE_METADATA_REPLY:
209             this.metaData = cmd.getBluePrint();
210             synchronized (this) {
211                 this.notifyAll();
212             }
213             break;
214         case JDBCCommand.TYPE_METADATA:
215             send(new JDBCCommand(this.adapter.getBluePrint()));
216             break;
217         case JDBCCommand.TYPE_EXECUTE_QUERY:
218             try {
219                 JDBCServer.execute(cmd.getRS(), adapter);
220                 send(new JDBCCommand(cmd.getRS(), JDBCCommand.TYPE_QUERY_REPLY));
221                 QueryUpdater u = new QueryUpdater(cmd.getRS());
222                 new Thread(u).start();
223             } catch (Exception err) {
224                 send(new JDBCCommand(err, cmd.getRSID()));
225             }
226             break;
227         case JDBCCommand.TYPE_QUERY_REPLY:
228             JDBCResultSet rs1 = JDBCStatement.getQuery(cmd.getRS().getID());
229             rs1.updateData(cmd.getRS());
230             break;
231         case JDBCCommand.TYPE_QUERY_RECORD:
232             JDBCResultSet rs2 = JDBCStatement.getQuery(cmd.getRSID());
233             rs2.addRecord(cmd.getRecord());
234             break;
235         case JDBCCommand.TYPE_QUERY_FINISH:
236             JDBCResultSet rs3 = JDBCStatement.removeQuery(cmd.getRSID());
237             rs3.setFinished(true);
238             break;
239         case JDBCCommand.TYPE_QUERY_ERROR:
240             System.err.println("ERROR Executing Query\n");
241             cmd.getERROR().printStackTrace();
242             JDBCResultSet rs4 = JDBCStatement.removeQuery(cmd.getRSID());
243             rs4.setError(cmd.getERROR());
244             rs4.setFinished(true);
245             synchronized (rs4) {
246                 rs4.notifyAll();
247             }
248         }
249     }
250
251     private class QueryUpdater implements Runnable {
252
253         private JDBCResultSet rs = null;
254
255         public QueryUpdater(JDBCResultSet _rs) {
256             this.rs = _rs;
257         }
258
259         public void run() {
260             while (rs.next()) {
261                 JDBCCommand rec = new JDBCCommand(rs.getCurrent(), rs.getID());
262                 send(rec);
263             }
264             JDBCCommand end = new JDBCCommand(rs.getID());
265             send(end);
266         }
267     }
268
269     public void send(Object o) {
270
271         if (this.socket == null) {
272             try {
273                 init();
274             } catch (Exception err) {
275                 err.printStackTrace();
276             }
277         }
278
279         try {
280             ByteArrayOutputStream bout = new ByteArrayOutputStream();
281             ObjectOutputStream oout = new ObjectOutputStream(bout);
282             oout.writeObject(o);
283             byte data[] = bout.toByteArray();
284             synchronized (socket) {
285                 out.writeInt(data.length);
286                 out.write(data);
287                 out.flush();
288             }
289         } catch (Exception err) {
290             err.printStackTrace();
291         }
292     }
293
294     @Override
295     public boolean isWrapperFor(Class<?> arg0) throws SQLException {
296         // TODO Auto-generated method stub
297         return false;
298     }
299
300     @Override
301     public <T> T unwrap(Class<T> arg0) throws SQLException {
302         // TODO Auto-generated method stub
303         return null;
304     }
305
306     @Override
307     public void clearWarnings() throws SQLException {
308         // TODO Auto-generated method stub
309
310     }
311
312     @Override
313     public void close() throws SQLException {
314         wasClosed = true;
315         try {
316             socket.close();
317         } catch (Exception err) {
318         }
319         socket = null;
320     }
321
322     @Override
323     public void commit() throws SQLException {
324         // TODO Auto-generated method stub
325
326     }
327
328     @Override
329     public Array createArrayOf(String typeName, Object[] elements)
330             throws SQLException {
331         // TODO Auto-generated method stub
332         return null;
333     }
334
335     @Override
336     public Blob createBlob() throws SQLException {
337         // TODO Auto-generated method stub
338         return null;
339     }
340
341     @Override
342     public Clob createClob() throws SQLException {
343         // TODO Auto-generated method stub
344         return null;
345     }
346
347     @Override
348     public NClob createNClob() throws SQLException {
349         // TODO Auto-generated method stub
350         return null;
351     }
352
353     @Override
354     public SQLXML createSQLXML() throws SQLException {
355         // TODO Auto-generated method stub
356         return null;
357     }
358
359     @Override
360     public Statement createStatement() throws SQLException {
361         return new JDBCStatement(this).getProxy();
362     }
363
364     @Override
365     public Statement createStatement(int resultSetType,
366             int resultSetConcurrency, int resultSetHoldability)
367             throws SQLException {
368         return new JDBCStatement(this).getProxy();
369     }
370
371     @Override
372     public Statement createStatement(int resultSetType, int resultSetConcurrency)
373             throws SQLException {
374         return new JDBCStatement(this).getProxy();
375     }
376
377     @Override
378     public Struct createStruct(String typeName, Object[] attributes)
379             throws SQLException {
380         // TODO Auto-generated method stub
381         return null;
382     }
383
384     @Override
385     public boolean getAutoCommit() throws SQLException {
386         // TODO Auto-generated method stub
387         return false;
388     }
389
390     @Override
391     public String getCatalog() throws SQLException {
392         // TODO Auto-generated method stub
393         return null;
394     }
395
396     @Override
397     public Properties getClientInfo() throws SQLException {
398         // TODO Auto-generated method stub
399         return null;
400     }
401
402     @Override
403     public String getClientInfo(String name) throws SQLException {
404         // TODO Auto-generated method stub
405         return null;
406     }
407
408     @Override
409     public int getHoldability() throws SQLException {
410         // TODO Auto-generated method stub
411         return 0;
412     }
413
414     @Override
415     public DatabaseMetaData getMetaData() throws SQLException {
416         if (this.metaData == null) {
417             JDBCCommand cmd = new JDBCCommand();
418             cmd.setType(JDBCCommand.TYPE_METADATA);
419             synchronized (this) {
420                 send(cmd);
421                 try {
422                     this.wait();
423                 } catch (Exception err) {
424                     err.printStackTrace();
425                 }
426             }
427         }
428         return metaData;
429     }
430
431     @Override
432     public int getTransactionIsolation() throws SQLException {
433         // TODO Auto-generated method stub
434         return 0;
435     }
436
437     @Override
438     public Map<String, Class<?>> getTypeMap() throws SQLException {
439         // TODO Auto-generated method stub
440         return null;
441     }
442
443     @Override
444     public SQLWarning getWarnings() throws SQLException {
445         // TODO Auto-generated method stub
446         return null;
447     }
448
449     @Override
450     public boolean isClosed() throws SQLException {
451         return false;
452     }
453
454     @Override
455     public boolean isReadOnly() throws SQLException {
456         // TODO Auto-generated method stub
457         return false;
458     }
459
460     @Override
461     public boolean isValid(int timeout) throws SQLException {
462         // TODO Auto-generated method stub
463         return false;
464     }
465
466     @Override
467     public String nativeSQL(String sql) throws SQLException {
468         // TODO Auto-generated method stub
469         return null;
470     }
471
472     @Override
473     public CallableStatement prepareCall(String sql, int resultSetType,
474             int resultSetConcurrency, int resultSetHoldability)
475             throws SQLException {
476         // TODO Auto-generated method stub
477         return null;
478     }
479
480     @Override
481     public CallableStatement prepareCall(String sql, int resultSetType,
482             int resultSetConcurrency) throws SQLException {
483         // TODO Auto-generated method stub
484         return null;
485     }
486
487     @Override
488     public CallableStatement prepareCall(String sql) throws SQLException {
489         // TODO Auto-generated method stub
490         return null;
491     }
492
493     @Override
494     public PreparedStatement prepareStatement(String sql, int resultSetType,
495             int resultSetConcurrency, int resultSetHoldability)
496             throws SQLException {
497         System.err.println("SQL 1=" + sql);
498         return new JDBCStatement(this, sql).getProxy();
499     }
500
501     @Override
502     public PreparedStatement prepareStatement(String sql, int resultSetType,
503             int resultSetConcurrency) throws SQLException {
504         System.err.println("SQL 2=" + sql);
505         return new JDBCStatement(this, sql).getProxy();
506     }
507
508     @Override
509     public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
510             throws SQLException {
511         System.err.println("SQL 3=" + sql);
512         return new JDBCStatement(this, sql).getProxy();
513     }
514
515     @Override
516     public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
517             throws SQLException {
518         System.err.println("SQL 4=" + sql);
519         return new JDBCStatement(this, sql).getProxy();
520     }
521
522     @Override
523     public PreparedStatement prepareStatement(String sql, String[] columnNames)
524             throws SQLException {
525         System.err.println("SQL 5=" + sql);
526         return new JDBCStatement(this, sql).getProxy();
527     }
528
529     @Override
530     public PreparedStatement prepareStatement(String sql) throws SQLException {
531         System.err.println("SQL 6=" + sql);
532         return new JDBCStatement(this, sql).getProxy();
533     }
534
535     @Override
536     public void releaseSavepoint(Savepoint savepoint) throws SQLException {
537         // TODO Auto-generated method stub
538
539     }
540
541     @Override
542     public void rollback() throws SQLException {
543         // TODO Auto-generated method stub
544
545     }
546
547     @Override
548     public void rollback(Savepoint savepoint) throws SQLException {
549         // TODO Auto-generated method stub
550
551     }
552
553     @Override
554     public void setAutoCommit(boolean autoCommit) throws SQLException {
555         // TODO Auto-generated method stub
556
557     }
558
559     @Override
560     public void setCatalog(String catalog) throws SQLException {
561         // TODO Auto-generated method stub
562
563     }
564
565     @Override
566     public void setClientInfo(Properties properties)
567             throws SQLClientInfoException {
568         // TODO Auto-generated method stub
569
570     }
571
572     @Override
573     public void setClientInfo(String name, String value)
574             throws SQLClientInfoException {
575         // TODO Auto-generated method stub
576
577     }
578
579     @Override
580     public void setHoldability(int holdability) throws SQLException {
581         // TODO Auto-generated method stub
582
583     }
584
585     @Override
586     public void setReadOnly(boolean readOnly) throws SQLException {
587         // TODO Auto-generated method stub
588
589     }
590
591     @Override
592     public Savepoint setSavepoint() throws SQLException {
593         // TODO Auto-generated method stub
594         return null;
595     }
596
597     @Override
598     public Savepoint setSavepoint(String name) throws SQLException {
599         // TODO Auto-generated method stub
600         return null;
601     }
602
603     @Override
604     public void setTransactionIsolation(int level) throws SQLException {
605         // TODO Auto-generated method stub
606
607     }
608
609     @Override
610     public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
611         // TODO Auto-generated method stub
612
613     }
614
615     @Override
616     public void setSchema(String schema) throws SQLException {
617         // TODO Auto-generated method stub
618
619     }
620
621     @Override
622     public String getSchema() throws SQLException {
623         // TODO Auto-generated method stub
624         return null;
625     }
626
627     @Override
628     public void abort(Executor executor) throws SQLException {
629         // TODO Auto-generated method stub
630
631     }
632
633     @Override
634     public void setNetworkTimeout(Executor executor, int milliseconds)
635             throws SQLException {
636         // TODO Auto-generated method stub
637
638     }
639
640     @Override
641     public int getNetworkTimeout() throws SQLException {
642         // TODO Auto-generated method stub
643         return 0;
644     }
645
646 }