11package org .jumpserver .chen .framework .console ;
22
33import com .google .gson .Gson ;
4- import org . apache . commons . lang3 . StringUtils ;
4+ import lombok . Getter ;
55import org .jumpserver .chen .framework .console .action .DataViewAction ;
6+ import org .jumpserver .chen .framework .console .context .ConsoleContext ;
67import org .jumpserver .chen .framework .console .dataview .DataView ;
78import org .jumpserver .chen .framework .console .dataview .UpdateDataView ;
89import org .jumpserver .chen .framework .console .entity .request .Connect ;
10+ import org .jumpserver .chen .framework .console .entity .request .SaveChangesRequest ;
911import org .jumpserver .chen .framework .console .entity .response .Message ;
1012import org .jumpserver .chen .framework .console .state .State ;
1113import org .jumpserver .chen .framework .console .state .StateManager ;
1214import org .jumpserver .chen .framework .datasource .Datasource ;
15+ import org .jumpserver .chen .framework .datasource .edit .TableBrowseSaveExecutionContext ;
16+ import org .jumpserver .chen .framework .datasource .edit .TableChangesPreviewService ;
17+ import org .jumpserver .chen .framework .datasource .edit .TableChangesSaveService ;
18+ import org .jumpserver .chen .framework .datasource .edit .TableEditContext ;
1319import org .jumpserver .chen .framework .i18n .MessageUtils ;
1420import org .jumpserver .chen .framework .jms .entity .CommandRecord ;
1521import org .jumpserver .chen .framework .session .SessionManager ;
22+ import org .jumpserver .chen .framework .session .controller .DialogHandle ;
1623import org .jumpserver .chen .framework .session .controller .dialog .Button ;
1724import org .jumpserver .chen .framework .session .controller .dialog .Dialog ;
18- import org .jumpserver .chen .framework .utils .TreeUtils ;
1925import org .jumpserver .chen .framework .ws .io .Packet ;
2026import org .jumpserver .wisp .Common ;
2127import org .springframework .web .socket .WebSocketSession ;
2228
2329import java .sql .SQLException ;
2430import java .util .Map ;
2531import java .util .concurrent .CountDownLatch ;
32+ import java .util .concurrent .TimeUnit ;
2633import java .util .concurrent .atomic .AtomicBoolean ;
34+ import java .util .concurrent .locks .ReentrantLock ;
2735
2836public class DataViewConsole extends AbstractConsole {
37+ private static final String PACKET_SAVE_CHANGES_PREVIEW_RESULT = "save_changes_preview_result" ;
38+ private static final String PACKET_SAVE_CHANGES_RESULT = "save_changes_result" ;
39+ private static final long WARNING_DIALOG_TIMEOUT_SECONDS = 300 ;
40+ private final TableChangesPreviewService tableChangesPreviewService = new TableChangesPreviewService ();
41+ private final TableChangesSaveService tableChangesSaveService = new TableChangesSaveService ();
2942
3043 private DataView tableDataView ;
3144 private StateManager <State > stateManager ;
45+ private final AtomicBoolean closed = new AtomicBoolean (false );
46+ private final ReentrantLock executionLock = new ReentrantLock ();
3247
33- private String schema ;
34- private String table ;
48+ @ Getter
49+ private final String schema ;
50+ @ Getter
51+ private final String table ;
3552
3653 private static final Gson GSON = new Gson ();
3754
38- public DataViewConsole (Datasource datasource , WebSocketSession ws , String nodeKey ) {
39- super (datasource , ws , nodeKey );
55+ public DataViewConsole (Datasource datasource , WebSocketSession ws , ConsoleContext context ) {
56+ super (datasource , ws , context );
57+ this .schema = context .schema ();
58+ this .table = context .table ();
4059 }
4160
4261
4362 @ Override
4463 public void onInit (Connect connect ) {
45- this .schema = TreeUtils .getValue (connect .getNodeKey (), "schema" );
46- this .table = StringUtils .isEmpty (TreeUtils .getValue (connect .getNodeKey (), "table" )) ?
47- TreeUtils .getValue (connect .getNodeKey (), "view" ) : TreeUtils .getValue (connect .getNodeKey (), "table" );
64+ if (!this .beginExecution ()) {
65+ return ;
66+ }
67+ try {
68+ this .initialize (connect );
69+ } finally {
70+ this .executionLock .unlock ();
71+ }
72+ }
4873
74+ private void initialize (Connect connect ) {
4975 var title = "" ;
5076 try {
5177 title = this .generateConsoleName ();
@@ -72,13 +98,32 @@ private String generateConsoleName() {
7298
7399 @ Override
74100 public void handle (Packet packet ) {
75- switch (packet .getType ()) {
76- case "ping" -> this .getPacketIO ().sendPacket ("pong" , null );
77- case Packet .TYPE_DATA_VIEW_ACTION -> {
78- var action = GSON .fromJson (GSON .toJson (packet .getData ()), DataViewAction .class );
79- this .onDataViewAction (action );
101+ if (!this .beginExecution ()) {
102+ return ;
103+ }
104+ try {
105+ switch (packet .getType ()) {
106+ case "ping" -> this .getPacketIO ().sendPacket ("pong" , null );
107+ case Packet .TYPE_DATA_VIEW_ACTION -> {
108+ var action = GSON .fromJson (GSON .toJson (packet .getData ()), DataViewAction .class );
109+ this .onDataViewAction (action );
110+ }
80111 }
112+ } finally {
113+ this .executionLock .unlock ();
114+ }
115+ }
116+
117+ private boolean beginExecution () {
118+ if (this .closed .get ()) {
119+ return false ;
81120 }
121+ this .executionLock .lock ();
122+ if (this .closed .get ()) {
123+ this .executionLock .unlock ();
124+ return false ;
125+ }
126+ return true ;
82127 }
83128
84129 public void onConnect (Connect connect ) {
@@ -145,21 +190,31 @@ public void createDataView(String schemaName, String tableName) {
145190 this .getConsoleLogger ().warn (MessageUtils .get ("ExecutionCanceled" ));
146191 }));
147192
148- SessionManager .getCurrentSession ().getController ().showDialog (dialog );
193+ var controller = SessionManager .getCurrentSession ().getController ();
194+ DialogHandle dialogHandle = controller .showDialog (dialog , () -> {
195+ hasNext .set (false );
196+ countDownLatch .countDown ();
197+ });
149198
150199 try {
151- countDownLatch .await ();
200+ if (!countDownLatch .await (WARNING_DIALOG_TIMEOUT_SECONDS , TimeUnit .SECONDS )) {
201+ hasNext .set (false );
202+ dialogHandle .cancel ();
203+ }
152204
153205 if (!hasNext .get ()) {
154206 throw new SQLException (MessageUtils .get ("ExecutionCanceled" ));
155207 }
156208
157209 } catch (InterruptedException e ) {
210+ Thread .currentThread ().interrupt ();
211+ hasNext .set (false );
158212 this .stateManager .commit ();
159213
160214 this .getConsoleLogger ().error ("get result error" );
215+ throw new SQLException (MessageUtils .get ("ExecutionCanceled" ), e );
161216 } finally {
162- SessionManager . getCurrentSession (). getController (). closeDialog ();
217+ dialogHandle . close ();
163218 }
164219 }
165220
@@ -181,6 +236,41 @@ public void createDataView(String schemaName, String tableName) {
181236
182237
183238 public void onDataViewAction (DataViewAction action ) {
239+ if (DataViewAction .ACTION_SAVE_CHANGES_PREVIEW .equals (action .getAction ())) {
240+ var request = GSON .fromJson (GSON .toJson (action .getData ()), SaveChangesRequest .class );
241+ var context = new TableEditContext (
242+ this .tableDataView .getTitle (),
243+ this .schema ,
244+ this .table ,
245+ this .tableDataView .getData ().getFields (),
246+ this .getDatasource ().getDruidDbType (),
247+ true
248+ );
249+ var result = this .tableChangesPreviewService .preview (context , action .getDataView (), request );
250+ this .getPacketIO ().sendPacket (PACKET_SAVE_CHANGES_PREVIEW_RESULT , result );
251+ return ;
252+ }
253+ if (DataViewAction .ACTION_SAVE_CHANGES .equals (action .getAction ())) {
254+ var request = GSON .fromJson (GSON .toJson (action .getData ()), SaveChangesRequest .class );
255+ var context = new TableEditContext (
256+ this .tableDataView .getTitle (),
257+ this .schema ,
258+ this .table ,
259+ this .tableDataView .getData ().getFields (),
260+ this .getDatasource ().getDruidDbType (),
261+ true
262+ );
263+ var result = this .tableChangesSaveService .save (
264+ context ,
265+ action .getDataView (),
266+ request ,
267+ new TableBrowseSaveExecutionContext (this .getDatasource ().getConnectionManager ()),
268+ SessionManager .getCurrentSession ()
269+ );
270+ this .getPacketIO ().sendPacket (PACKET_SAVE_CHANGES_RESULT , result );
271+ return ;
272+ }
273+
184274 try {
185275 this .tableDataView .getStateManager ().getState ().setLoading (true );
186276 this .tableDataView .getStateManager ().commit ();
@@ -199,5 +289,24 @@ public void onDataViewAction(DataViewAction action) {
199289
200290 @ Override
201291 public void close () {
292+ if (!this .closed .compareAndSet (false , true )) {
293+ return ;
294+ }
295+ var currentSession = SessionManager .getCurrentSession ();
296+ if (currentSession == null && this .getPacketIO ().getWsSession ().getAttributes () != null ) {
297+ Object token = this .getPacketIO ().getWsSession ().getAttributes ().get ("token" );
298+ if (token instanceof String sessionToken ) {
299+ currentSession = SessionManager .getSession (sessionToken );
300+ }
301+ }
302+ if (currentSession != null && currentSession .getController () != null ) {
303+ currentSession .getController ().cancelDialogs (this .getPacketIO ().getWsSession ().getId ());
304+ }
305+ this .executionLock .lock ();
306+ try {
307+ // Wait for admitted work to observe cancellation and leave the execution section.
308+ } finally {
309+ this .executionLock .unlock ();
310+ }
202311 }
203312}
0 commit comments