From 7347060caaee0ac151805a1c478fe1cedf6723bf Mon Sep 17 00:00:00 2001 From: Grzesiek Bylica Date: Thu, 8 Nov 2018 14:00:11 +0100 Subject: [PATCH] #727 added sleep httpRetriver datasource --- .../form/SleepAndReactivationDS.vue | 176 ++++++++++++++++++ ScadaLTS-UI-1/src/main.js | 5 +- .../WEB-INF/classes/messages_de.properties | 4 + .../WEB-INF/classes/messages_en.properties | 6 +- .../WEB-INF/classes/messages_es.properties | 6 +- .../WEB-INF/classes/messages_fi.properties | 4 + .../WEB-INF/classes/messages_fr.properties | 6 +- .../WEB-INF/classes/messages_lu.properties | 6 +- .../WEB-INF/classes/messages_nl.properties | 6 +- .../WEB-INF/classes/messages_pl.properties | 6 +- .../WEB-INF/classes/messages_pt.properties | 4 + .../WEB-INF/classes/messages_ru.properties | 6 +- .../WEB-INF/classes/messages_zh.properties | 6 +- WebContent/WEB-INF/jsp/dataSourceEdit.jsp | 2 +- .../jsp/dataSourceEdit/editHttpRetriever.jsp | 65 +++++-- .../serotonin/mango/rt/RuntimeManager.java | 12 +- .../mango/rt/dataSource/DataSourceRT.java | 14 +- .../http/HttpRetrieverDataSourceRT.java | 49 ++++- .../mango/vo/dataSource/DataSourceVO.java | 9 +- .../http/HttpRetrieverDataSourceVO.java | 29 ++- .../dataSource/http/ICheckReactivation.java | 9 + .../mango/web/dwr/DataSourceEditDwr.java | 23 +++ src/org/scada_lts/dao/SerializationData.java | 14 +- src/org/scada_lts/ds/StartStopDsRT.java | 44 +++++ src/org/scada_lts/ds/StopDsRT.java | 34 ---- .../scada_lts/ds/model/ReactivationDs.java | 82 ++++++++ .../ds/reactivation/MenagerReactivation.java | 114 ++++++++++++ .../ReactivationConnectHttpRetriever.java | 56 ++++++ src/org/scada_lts/ds/state/SleepStateDs.java | 19 ++ .../scada_lts/ds/state/StartSleepStateDs.java | 20 ++ .../ds/state/change/AlertObserver.java | 28 +++ .../ds/state/change/ChangeStatus.java | 33 ++++ .../web/mvc/api/ReactivationDsAPI.java | 41 ++++ 33 files changed, 853 insertions(+), 85 deletions(-) create mode 100644 ScadaLTS-UI-1/src/components/form/SleepAndReactivationDS.vue create mode 100644 src/com/serotonin/mango/vo/dataSource/http/ICheckReactivation.java create mode 100644 src/org/scada_lts/ds/StartStopDsRT.java delete mode 100644 src/org/scada_lts/ds/StopDsRT.java create mode 100644 src/org/scada_lts/ds/model/ReactivationDs.java create mode 100644 src/org/scada_lts/ds/reactivation/MenagerReactivation.java create mode 100644 src/org/scada_lts/ds/reactivation/ReactivationConnectHttpRetriever.java create mode 100644 src/org/scada_lts/ds/state/SleepStateDs.java create mode 100644 src/org/scada_lts/ds/state/StartSleepStateDs.java create mode 100644 src/org/scada_lts/ds/state/change/AlertObserver.java create mode 100644 src/org/scada_lts/ds/state/change/ChangeStatus.java create mode 100644 src/org/scada_lts/web/mvc/api/ReactivationDsAPI.java diff --git a/ScadaLTS-UI-1/src/components/form/SleepAndReactivationDS.vue b/ScadaLTS-UI-1/src/components/form/SleepAndReactivationDS.vue new file mode 100644 index 0000000000..84c876a584 --- /dev/null +++ b/ScadaLTS-UI-1/src/components/form/SleepAndReactivationDS.vue @@ -0,0 +1,176 @@ + + + + + diff --git a/ScadaLTS-UI-1/src/main.js b/ScadaLTS-UI-1/src/main.js index 793acd7f79..6a5d21227c 100644 --- a/ScadaLTS-UI-1/src/main.js +++ b/ScadaLTS-UI-1/src/main.js @@ -8,6 +8,8 @@ import Test from './components/Test' import IsAlive from './components/IsAlive' import ExportImportPointHierarchy from './components/ExportImportPointHierarchy' import SimpleComponentSVG from './components/SimpleComponentSVG' + +import SleepAndReactivationDS from './components/form/SleepAndReactivationDS' import router from './router' import VJsoneditor from 'vue-jsoneditor'; import Vuetify from 'vuetify'; @@ -52,7 +54,8 @@ new Vue({ el: '#app', components: { "simple-component-svg": SimpleComponentSVG, - "export-import-ph": ExportImportPointHierarchy + "export-import-ph": ExportImportPointHierarchy, + "sleep-reactivation-ds": SleepAndReactivationDS, } }) diff --git a/WebContent/WEB-INF/classes/messages_de.properties b/WebContent/WEB-INF/classes/messages_de.properties index 924f9a741b..31afc2899c 100644 --- a/WebContent/WEB-INF/classes/messages_de.properties +++ b/WebContent/WEB-INF/classes/messages_de.properties @@ -3162,6 +3162,10 @@ ds.state.importChangeEnableStateDs=During the import, the on/off status of DataS ds.state.scryptChangeEnable=The script has changed the on/off status of datasource ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default dsList.statusDescribe=Status description +event.reactivation.sleep=Data source has been sleeped +event.ds.describe={1} +ds.state.sleep=Data source has been sleeped after several attempted connections had failed +ds.state.startSleep=Data source has been started after sleeped diff --git a/WebContent/WEB-INF/classes/messages_en.properties b/WebContent/WEB-INF/classes/messages_en.properties index 8d218bd1fe..dc4a47feb0 100644 --- a/WebContent/WEB-INF/classes/messages_en.properties +++ b/WebContent/WEB-INF/classes/messages_en.properties @@ -3165,4 +3165,8 @@ ds.state.apiChangeEnableStateDs=\ With the use of the API, the on/off status of ds.state.importChangeEnableStateDs=During the import, the on/off status of DataSource was changed ds.state.scryptChangeEnable=The script has changed the on/off status of datasource ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default -dsList.statusDescribe=Status description \ No newline at end of file +dsList.statusDescribe=Status description +event.reactivation.sleep=Data source has been sleeped +event.ds.describe={1} +ds.state.startSleep=Data source has been started after sleeped +ds.state.sleep=Data source has been sleeped after several attempted connections had failed \ No newline at end of file diff --git a/WebContent/WEB-INF/classes/messages_es.properties b/WebContent/WEB-INF/classes/messages_es.properties index 6956a84c67..a0b2a29ed4 100644 --- a/WebContent/WEB-INF/classes/messages_es.properties +++ b/WebContent/WEB-INF/classes/messages_es.properties @@ -3090,4 +3090,8 @@ ds.state.apiChangeEnableStateDs=With the use of the API, the on/off status of Da ds.state.importChangeEnableStateDs=During the import, the on/off status of DataSource was changed ds.state.scryptChangeEnable=The script has changed the on/off status of datasource ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default -dsList.statusDescribe=Status description \ No newline at end of file +dsList.statusDescribe=Status description +event.reactivation.sleep=Data source has been sleeped +event.ds.describe={1} +ds.state.startSleep=Data source has been started after sleeped +ds.state.sleep=Data source has been sleeped after several attempted connections had failed \ No newline at end of file diff --git a/WebContent/WEB-INF/classes/messages_fi.properties b/WebContent/WEB-INF/classes/messages_fi.properties index e08539e355..7b8d5b4989 100644 --- a/WebContent/WEB-INF/classes/messages_fi.properties +++ b/WebContent/WEB-INF/classes/messages_fi.properties @@ -2912,3 +2912,7 @@ ds.state.importChangeEnableStateDs=During the import, the on/off status of DataS ds.state.scryptChangeEnable=The script has changed the on/off status of datasource ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default dsList.statusDescribe=Status description +event.reactivation.sleep=Data source has been sleeped +event.ds.describe={1} +ds.state.startSleep=Data source has been started after sleeped +ds.state.sleep=Data source has been sleeped after several attempted connections had failed diff --git a/WebContent/WEB-INF/classes/messages_fr.properties b/WebContent/WEB-INF/classes/messages_fr.properties index f6c856122b..07f6232258 100644 --- a/WebContent/WEB-INF/classes/messages_fr.properties +++ b/WebContent/WEB-INF/classes/messages_fr.properties @@ -3166,4 +3166,8 @@ ds.state.apiChangeEnableStateDs=With the use of the API, the on/off status of Da ds.state.importChangeEnableStateDs=During the import, the on/off status of DataSource was changed ds.state.scryptChangeEnable=The script has changed the on/off status of datasource ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default -dsList.statusDescribe=Status description \ No newline at end of file +dsList.statusDescribe=Status description +event.reactivation.sleep=Data source has been sleeped +event.ds.describe={1} +ds.state.startSleep=Data source has been started after sleeped +ds.state.sleep=Data source has been sleeped after several attempted connections had failed \ No newline at end of file diff --git a/WebContent/WEB-INF/classes/messages_lu.properties b/WebContent/WEB-INF/classes/messages_lu.properties index 6c48e7027c..52bc3f2a77 100644 --- a/WebContent/WEB-INF/classes/messages_lu.properties +++ b/WebContent/WEB-INF/classes/messages_lu.properties @@ -3176,4 +3176,8 @@ ds.state.apiChangeEnableStateDs=With the use of the API, the on/off status of Da ds.state.importChangeEnableStateDs=During the import, the on/off status of DataSource was changed ds.state.scryptChangeEnable=The script has changed the on/off status of datasource ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default -dsList.statusDescribe=Status description \ No newline at end of file +dsList.statusDescribe=Status description +event.reactivation.sleep=Data source has been sleeped +event.ds.describe={1} +ds.state.startSleep=Data source has been started after sleeped +ds.state.sleep=Data source has been sleeped after several attempted connections had failed \ No newline at end of file diff --git a/WebContent/WEB-INF/classes/messages_nl.properties b/WebContent/WEB-INF/classes/messages_nl.properties index 4ddcfacebf..77087b9771 100644 --- a/WebContent/WEB-INF/classes/messages_nl.properties +++ b/WebContent/WEB-INF/classes/messages_nl.properties @@ -2716,4 +2716,8 @@ ds.state.apiChangeEnableStateDs=With the use of the API, the on/off status of Da ds.state.importChangeEnableStateDs=During the import, the on/off status of DataSource was changed ds.state.scryptChangeEnable=The script has changed the on/off status of datasource ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default -dsList.statusDescribe=Status description \ No newline at end of file +dsList.statusDescribe=Status description +event.reactivation.sleep=Data source has been sleeped +event.ds.describe={1} +ds.state.startSleep=Data source has been started after sleeped +ds.state.sleep=Data source has been sleeped after several attempted connections had failed \ No newline at end of file diff --git a/WebContent/WEB-INF/classes/messages_pl.properties b/WebContent/WEB-INF/classes/messages_pl.properties index 1bb9c37996..37fe88cc5a 100644 --- a/WebContent/WEB-INF/classes/messages_pl.properties +++ b/WebContent/WEB-INF/classes/messages_pl.properties @@ -3078,4 +3078,8 @@ ds.state.apiChangeEnableStateDs=With the use of the API, the on/off status of Da ds.state.importChangeEnableStateDs=During the import, the on/off status of DataSource was changed ds.state.scryptChangeEnable=The script has changed the on/off status of datasource ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default -dsList.statusDescribe=Status description \ No newline at end of file +dsList.statusDescribe=Status description +event.reactivation.sleep=Data source has been sleeped +event.ds.describe={1} +ds.state.startSleep=Data source has been started after sleeped +ds.state.sleep=Data source has been sleeped after several attempted connections had failed \ No newline at end of file diff --git a/WebContent/WEB-INF/classes/messages_pt.properties b/WebContent/WEB-INF/classes/messages_pt.properties index fd2938b7fd..101fa714ed 100644 --- a/WebContent/WEB-INF/classes/messages_pt.properties +++ b/WebContent/WEB-INF/classes/messages_pt.properties @@ -3157,3 +3157,7 @@ ds.state.importChangeEnableStateDs=During the import, the on/off status of DataS ds.state.scryptChangeEnable=The script has changed the on/off status of datasource ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default dsList.statusDescribe=Status description +event.reactivation.sleep=Data source has been sleeped +event.ds.describe={1} +ds.state.startSleep=Data source has been started after sleeped +ds.state.sleep=Data source has been sleeped after several attempted connections had failed diff --git a/WebContent/WEB-INF/classes/messages_ru.properties b/WebContent/WEB-INF/classes/messages_ru.properties index af512dc5a9..59836183bc 100644 --- a/WebContent/WEB-INF/classes/messages_ru.properties +++ b/WebContent/WEB-INF/classes/messages_ru.properties @@ -3127,4 +3127,8 @@ ds.state.apiChangeEnableStateDs=With the use of the API, the on/off status of Da ds.state.importChangeEnableStateDs=During the import, the on/off status of DataSource was changed ds.state.scryptChangeEnable=The script has changed the on/off status of datasource ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default -dsList.statusDescribe=Status description \ No newline at end of file +dsList.statusDescribe=Status description +event.reactivation.sleep=Data source has been sleeped +event.ds.describe={1} +ds.state.startSleep=Data source has been started after sleeped +ds.state.sleep=Data source has been sleeped after several attempted connections had failed \ No newline at end of file diff --git a/WebContent/WEB-INF/classes/messages_zh.properties b/WebContent/WEB-INF/classes/messages_zh.properties index b5b563a95a..4913c31152 100644 --- a/WebContent/WEB-INF/classes/messages_zh.properties +++ b/WebContent/WEB-INF/classes/messages_zh.properties @@ -2030,4 +2030,8 @@ ds.state.apiChangeEnableStateDs=With the use of the API, the on/off status of Da ds.state.importChangeEnableStateDs=During the import, the on/off status of DataSource was changed ds.state.scryptChangeEnable=The script has changed the on/off status of datasource ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default -dsList.statusDescribe=Status description \ No newline at end of file +dsList.statusDescribe=Status description +event.reactivation.sleep=Data source has been sleeped +event.ds.describe={1} +ds.state.startSleep=Data source has been started after sleeped +ds.state.sleep=Data source has been sleeped after several attempted connections had failed \ No newline at end of file diff --git a/WebContent/WEB-INF/jsp/dataSourceEdit.jsp b/WebContent/WEB-INF/jsp/dataSourceEdit.jsp index 47437c7beb..46326ded40 100644 --- a/WebContent/WEB-INF/jsp/dataSourceEdit.jsp +++ b/WebContent/WEB-INF/jsp/dataSourceEdit.jsp @@ -73,7 +73,7 @@ rowCreator: function(options) { var tr = document.createElement("tr"); tr.mangoId = "p"+ options.rowData.id; - tr.className = "row"+ (options.rowIndex % 2 == 0 ? "" : "Alt"); + tr.className = ""+ (options.rowIndex % 2 == 0 ? "" : "rowAlt"); return tr; }, cellCreator: function(options) { diff --git a/WebContent/WEB-INF/jsp/dataSourceEdit/editHttpRetriever.jsp b/WebContent/WEB-INF/jsp/dataSourceEdit/editHttpRetriever.jsp index bdb6a4ee75..6445cd7554 100644 --- a/WebContent/WEB-INF/jsp/dataSourceEdit/editHttpRetriever.jsp +++ b/WebContent/WEB-INF/jsp/dataSourceEdit/editHttpRetriever.jsp @@ -18,8 +18,31 @@ --%> <%@ include file="/WEB-INF/jsp/include/tech.jsp" %> <%@page import="com.serotonin.mango.DataTypes"%> + + @@ -146,12 +180,12 @@ - Stop
- (It will disable the datasource
-  when the attempted connections fail) + +
+ +
- @@ -227,4 +261,5 @@ - \ No newline at end of file + +<%@ include file="/WEB-INF/jsp/include/tech-vuejs.jsp"%> \ No newline at end of file diff --git a/src/com/serotonin/mango/rt/RuntimeManager.java b/src/com/serotonin/mango/rt/RuntimeManager.java index 7f5b21f796..4dcf88e77d 100644 --- a/src/com/serotonin/mango/rt/RuntimeManager.java +++ b/src/com/serotonin/mango/rt/RuntimeManager.java @@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; +import com.serotonin.mango.vo.dataSource.http.ICheckReactivation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; @@ -127,7 +128,14 @@ synchronized public void initialize(boolean safe) { List> configs = dataSourceDao.getDataSources(); List> pollingRound = new ArrayList>(); for (DataSourceVO config : configs) { - if (config.isEnabled()) { + + boolean isCheckToTrayEnableRun = (config instanceof ICheckReactivation); + boolean isToTrayEnable = false; + if (isCheckToTrayEnableRun) { + isToTrayEnable = ((ICheckReactivation) config).checkToTrayEnable(); + } + + if (config.isEnabled() || isToTrayEnable ) { if (safe) { config.setEnabled(false); dataSourceDao.saveDataSource(config); @@ -310,7 +318,7 @@ private boolean initializeDataSource(DataSourceVO vo) { return false; // Ensure that the data source is enabled. - Assert.isTrue(vo.isEnabled()); + // Assert.isTrue(vo.isEnabled()); // Create and initialize the runtime version of the data source. DataSourceRT dataSource = vo.createDataSourceRT(); diff --git a/src/com/serotonin/mango/rt/dataSource/DataSourceRT.java b/src/com/serotonin/mango/rt/dataSource/DataSourceRT.java index 1443edf096..669eda1605 100644 --- a/src/com/serotonin/mango/rt/dataSource/DataSourceRT.java +++ b/src/com/serotonin/mango/rt/dataSource/DataSourceRT.java @@ -21,10 +21,7 @@ import gnu.io.NoSuchPortException; import gnu.io.PortInUseException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import com.serotonin.ShouldNeverHappenException; import com.serotonin.mango.Common; @@ -137,6 +134,15 @@ public void forcePointRead(@SuppressWarnings("unused") DataPointRT dataPoint) { // No op by default. Override as required. } + public static void raiseEvent(String describe, DataSourceVO vo) { + LocalizableMessage message = new LocalizableMessage("event.ds.describe", "", describe); + int urgentAlarmLevel = 2; + DataSourceEventType dset = new DataSourceEventType(vo.getId(), vo.getId(), urgentAlarmLevel, 0); + Map context = new HashMap(); + context.put("dataSource", vo); + Common.ctx.getEventManager().raiseEvent(dset, new Date().getTime(), true, dset.getAlarmLevel(), message, context); + } + protected void raiseEvent(int eventId, long time, boolean rtn, LocalizableMessage message) { message = new LocalizableMessage("event.ds", vo.getName(), message); DataSourceEventType type = getEventType(eventId); diff --git a/src/com/serotonin/mango/rt/dataSource/http/HttpRetrieverDataSourceRT.java b/src/com/serotonin/mango/rt/dataSource/http/HttpRetrieverDataSourceRT.java index dac60d3166..c018c29582 100644 --- a/src/com/serotonin/mango/rt/dataSource/http/HttpRetrieverDataSourceRT.java +++ b/src/com/serotonin/mango/rt/dataSource/http/HttpRetrieverDataSourceRT.java @@ -35,9 +35,12 @@ import com.serotonin.web.http.HttpUtils; import com.serotonin.web.i18n.LocalizableException; import com.serotonin.web.i18n.LocalizableMessage; -import org.scada_lts.ds.StopDsRT; - -import java.util.Date; +import org.scada_lts.ds.StartStopDsRT; +import org.scada_lts.ds.model.ReactivationDs; +import org.scada_lts.ds.reactivation.MenagerReactivation; +import org.scada_lts.ds.reactivation.ReactivationConnectHttpRetriever; +import org.scada_lts.ds.state.SleepStateDs; +import org.scada_lts.ds.state.StopChangeEnableStateDs; /** * @author Matthew Lohbihler @@ -71,7 +74,7 @@ public void setPointValue(DataPointRT dataPoint, PointValueTime valueTime, SetPo protected void doPoll(long time) { String data; try { - data = getData(vo.getUrl(), vo.getTimeoutSeconds(), vo.getRetries(), vo.isStop()); + data = getData(vo.getUrl(), vo.getTimeoutSeconds(), vo.getRetries(), vo.isStop(), vo.getReactivation()); } catch (Exception e) { LocalizableMessage lm; if (e instanceof LocalizableException) @@ -119,7 +122,31 @@ protected void doPoll(long time) { returnToNormal(PARSE_EXCEPTION_EVENT, time); } - public String getData(String url, int timeoutSeconds, int retries, boolean stop) throws LocalizableException { + public static boolean testConnection(String url, int timeoutSeconds, int retries) { + String data = ""; + for (int i = 0; i <= retries; i++) { + HttpClient client = Common.getHttpClient(timeoutSeconds * 1000); + GetMethod method = null; + LocalizableMessage message; + try { + method = new GetMethod(url); + int responseCode = client.executeMethod(method); + if (responseCode == HttpStatus.SC_OK) { + data = HttpUtils.readResponseBody(method, READ_LIMIT); + return true; + } + message = new LocalizableMessage("event.http.response", url, responseCode); + } catch (Exception e) { + message = DataSourceRT.getExceptionMessage(e); + } finally { + if (method != null) + method.releaseConnection(); + } + } + return false; + } + + public String getData(String url, int timeoutSeconds, int retries, boolean stop, ReactivationDs r) throws LocalizableException { String data = ""; for (int i = 0; i <= retries; i++) { HttpClient client = Common.getHttpClient(timeoutSeconds * 1000); @@ -141,11 +168,15 @@ public String getData(String url, int timeoutSeconds, int retries, boolean stop) } if (retries == i && stop) { - LocalizableMessage lm = new LocalizableMessage("event.httpRetriever.retrievalError", vo.getUrl(), "Data source has been stopped/interrupted after several attempted connections had failed"); - raiseEvent(DATA_RETRIEVAL_FAILURE_EVENT, new Date().getTime(), true, lm); - StopDsRT stopDsRT = new StopDsRT(vo.getId()); + StartStopDsRT stopDsRT = new StartStopDsRT(vo.getId(), false, new StopChangeEnableStateDs()); + new Thread(stopDsRT).start(); + } else if (retries == i && r.isSleep()) { + ReactivationConnectHttpRetriever rhr = new ReactivationConnectHttpRetriever(); + MenagerReactivation.getInstance().addProcess(rhr, r, vo); + StartStopDsRT stopDsRT = new StartStopDsRT(vo.getId(),false, new SleepStateDs()); new Thread(stopDsRT).start(); - } else if (retries == i) { + } + else if (retries == i) { throw new LocalizableException(message); } } diff --git a/src/com/serotonin/mango/vo/dataSource/DataSourceVO.java b/src/com/serotonin/mango/vo/dataSource/DataSourceVO.java index 311296687e..be1b1f2907 100644 --- a/src/com/serotonin/mango/vo/dataSource/DataSourceVO.java +++ b/src/com/serotonin/mango/vo/dataSource/DataSourceVO.java @@ -69,6 +69,7 @@ import com.serotonin.web.i18n.LocalizableMessage; import org.scada_lts.ds.state.MigrationOrErrorSerializeChangeEnableState; import org.scada_lts.ds.state.IStateDs; +import org.scada_lts.ds.state.change.ChangeStatus; import java.io.IOException; import java.io.ObjectInputStream; @@ -76,7 +77,7 @@ import java.io.Serializable; import java.util.*; -abstract public class DataSourceVO> implements +abstract public class DataSourceVO> extends ChangeStatus implements Serializable, Cloneable, JsonSerializable, ChangeComparable { public enum Type { EBI25(16, "dsEdit.ebi25", false) { @@ -397,11 +398,15 @@ public void setEnabled(boolean enabled) { } public IStateDs getState() { + return state; } public void setState(IStateDs state) { - this.state = state; + notifyListeners( + this, + this.state, + this.state = state); } public int getId() { diff --git a/src/com/serotonin/mango/vo/dataSource/http/HttpRetrieverDataSourceVO.java b/src/com/serotonin/mango/vo/dataSource/http/HttpRetrieverDataSourceVO.java index b9897b2b0c..999309b03f 100644 --- a/src/com/serotonin/mango/vo/dataSource/http/HttpRetrieverDataSourceVO.java +++ b/src/com/serotonin/mango/vo/dataSource/http/HttpRetrieverDataSourceVO.java @@ -40,12 +40,13 @@ import com.serotonin.util.StringUtils; import com.serotonin.web.dwr.DwrResponseI18n; import com.serotonin.web.i18n.LocalizableMessage; +import org.scada_lts.ds.model.ReactivationDs; /** * @author Matthew Lohbihler */ @JsonRemoteEntity -public class HttpRetrieverDataSourceVO extends DataSourceVO { +public class HttpRetrieverDataSourceVO extends DataSourceVO implements ICheckReactivation{ public static final Type TYPE = Type.HTTP_RETRIEVER; @Override @@ -100,6 +101,9 @@ public HttpRetrieverPointLocatorVO createPointLocator() { @JsonRemoteProperty private boolean stop = false; + @JsonRemoteProperty + private ReactivationDs reactivation = new ReactivationDs(); + public String getUrl() { return url; } @@ -148,7 +152,13 @@ public void setStop(boolean stop) { this.stop = stop; } + public ReactivationDs getReactivation() { + return reactivation; + } + public void setReactivation(ReactivationDs reactivation) { + this.reactivation = reactivation; + } @Override public void validate(DwrResponseI18n response) { @@ -171,7 +181,8 @@ protected void addPropertiesImpl(List list) { AuditEventType.addPropertyMessage(list, "dsEdit.httpRetriever.url", url); AuditEventType.addPropertyMessage(list, "dsEdit.httpRetriever.timeout", timeoutSeconds); AuditEventType.addPropertyMessage(list, "dsEdit.httpRetriever.retries", retries); - AuditEventType.addPropertyMessage(list, "dsEdit.httpRetriever.retries", stop ); + AuditEventType.addPropertyMessage(list, "dsEdit.httpRetriever.stop", stop ); + AuditEventType.addPropertyMessage(list, "dsEdit.httpRetriever.reactivation", reactivation ); } @Override @@ -182,7 +193,8 @@ protected void addPropertyChangesImpl(List list, HttpRetriev AuditEventType.maybeAddPropertyChangeMessage(list, "dsEdit.httpRetriever.timeout", from.timeoutSeconds, timeoutSeconds); AuditEventType.maybeAddPropertyChangeMessage(list, "dsEdit.httpRetriever.retries", from.retries, retries); - AuditEventType.maybeAddPropertyChangeMessage(list, "dsEdit.httpRetriever.retries", from.stop, stop); + AuditEventType.maybeAddPropertyChangeMessage(list, "dsEdit.httpRetriever.stop", from.stop, stop); + AuditEventType.maybeAddPropertyChangeMessage(list, "dsEdit.httpRetriever.reactivation", from.stop, stop); } // @@ -201,6 +213,7 @@ private void writeObject(ObjectOutputStream out) throws IOException { out.writeInt(timeoutSeconds); out.writeInt(retries); out.writeBoolean(stop); + out.writeObject(reactivation); } private void readObject(ObjectInputStream in) throws IOException { @@ -219,6 +232,11 @@ private void readObject(ObjectInputStream in) throws IOException { } catch (Exception e) { stop = false; } + try { + reactivation = (ReactivationDs) in.readObject(); + } catch (Exception e) { + reactivation = new ReactivationDs(false, (short) 1,(short) 1); + } } } @@ -235,4 +253,9 @@ public void jsonSerialize(Map map) { super.jsonSerialize(map); serializeUpdatePeriodType(map, updatePeriodType); } + + @Override + public boolean checkToTrayEnable() { + return isEnabled() || isStop() || reactivation.isSleep(); + } } diff --git a/src/com/serotonin/mango/vo/dataSource/http/ICheckReactivation.java b/src/com/serotonin/mango/vo/dataSource/http/ICheckReactivation.java new file mode 100644 index 0000000000..df026fe383 --- /dev/null +++ b/src/com/serotonin/mango/vo/dataSource/http/ICheckReactivation.java @@ -0,0 +1,9 @@ +package com.serotonin.mango.vo.dataSource.http; + +/** + * @autor grzegorz.bylica@gmail.com on 31.10.18 + */ +public interface ICheckReactivation { + + boolean checkToTrayEnable(); +} diff --git a/src/com/serotonin/mango/web/dwr/DataSourceEditDwr.java b/src/com/serotonin/mango/web/dwr/DataSourceEditDwr.java index 279be9a532..990d0ce3c4 100644 --- a/src/com/serotonin/mango/web/dwr/DataSourceEditDwr.java +++ b/src/com/serotonin/mango/web/dwr/DataSourceEditDwr.java @@ -88,6 +88,7 @@ import com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier; import com.serotonin.db.IntValuePair; import com.serotonin.io.StreamUtils; +import org.scada_lts.ds.model.ReactivationDs; import org.scada_lts.modbus.SerialParameters; import com.serotonin.mango.Common; import com.serotonin.mango.DataTypes; @@ -1280,6 +1281,28 @@ public DwrResponseI18n saveHttpRetrieverDataSource(String name, String xid, return tryDataSourceSave(ds); } + @MethodFilter + public DwrResponseI18n saveHttpRetrieverDataSourceWithReactivationOptions(String name, String xid, + int updatePeriods, int updatePeriodType, String url, + int timeoutSeconds, int retries, boolean stop, boolean sleep, short typeReactivation, short valueReactivation) { + HttpRetrieverDataSourceVO ds = (HttpRetrieverDataSourceVO) Common + .getUser().getEditDataSource(); + + ds.setXid(xid); + ds.setName(name); + ds.setUpdatePeriods(updatePeriods); + ds.setUpdatePeriodType(updatePeriodType); + ds.setUrl(url); + ds.setTimeoutSeconds(timeoutSeconds); + ds.setRetries(retries); + ds.setStop(stop); + ReactivationDs rDs = new ReactivationDs(sleep, typeReactivation, valueReactivation); + ds.setReactivation(rDs); + + return tryDataSourceSave(ds); + } + + @MethodFilter public DwrResponseI18n saveHttpRetrieverPointLocator(int id, String xid, String name, HttpRetrieverPointLocatorVO locator) { diff --git a/src/org/scada_lts/dao/SerializationData.java b/src/org/scada_lts/dao/SerializationData.java index 703fdca15c..dd44cff302 100644 --- a/src/org/scada_lts/dao/SerializationData.java +++ b/src/org/scada_lts/dao/SerializationData.java @@ -40,12 +40,14 @@ public class SerializationData { public Object readObject(final InputStream is) { if (is != null) { - try { - return new ObjectInputStream(is).readObject(); - } catch (ClassNotFoundException | IOException e) { - LOG.error(e); - throw new StreamDaoException(e); - } + synchronized (is) { + try { + return new ObjectInputStream(is).readObject(); + } catch (ClassNotFoundException | IOException e) { + LOG.error(e); + throw new StreamDaoException(e); + } + } } return null; } diff --git a/src/org/scada_lts/ds/StartStopDsRT.java b/src/org/scada_lts/ds/StartStopDsRT.java new file mode 100644 index 0000000000..dcc27caba9 --- /dev/null +++ b/src/org/scada_lts/ds/StartStopDsRT.java @@ -0,0 +1,44 @@ +package org.scada_lts.ds; + +import com.serotonin.mango.Common; +import com.serotonin.mango.rt.RuntimeManager; +import com.serotonin.mango.vo.dataSource.DataSourceVO; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.scada_lts.ds.state.IStateDs; +import org.scada_lts.ds.state.change.AlertObserver; + +/** + * @project Scada-LTS + * @autor grzegorz.bylica@gmail.com on 05.10.18 + */ +public class StartStopDsRT implements Runnable { + + private static final Log LOG = LogFactory.getLog(StartStopDsRT.class); + + private int idDs; + private boolean enable; + private IStateDs state; + + public StartStopDsRT(int idDs, boolean enable, IStateDs state) { + this.idDs = idDs; + this.enable = enable; + this.state = state; + } + + @Override + public void run() { + try { + RuntimeManager runtimeManager = Common.ctx.getRuntimeManager(); + DataSourceVO dataSource = runtimeManager.getDataSource(idDs); + new AlertObserver(dataSource); + dataSource.setEnabled(enable); + dataSource.setState(state); + runtimeManager.saveDataSource(dataSource); + + } catch (Exception e) { + LOG.error(e); + } + + } +} diff --git a/src/org/scada_lts/ds/StopDsRT.java b/src/org/scada_lts/ds/StopDsRT.java deleted file mode 100644 index bac6e662d5..0000000000 --- a/src/org/scada_lts/ds/StopDsRT.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.scada_lts.ds; - -import com.serotonin.mango.Common; -import com.serotonin.mango.rt.RuntimeManager; -import com.serotonin.mango.vo.dataSource.DataSourceVO; -import org.scada_lts.ds.state.StopChangeEnableStateDs; - -/** - * @project Scada-LTS - * @autor grzegorz.bylica@gmail.com on 05.10.18 - */ -public class StopDsRT implements Runnable { - - private int idDs; - - public StopDsRT(int idDs) { - this.idDs = idDs; - } - - @Override - public void run() { - try { - RuntimeManager runtimeManager = Common.ctx.getRuntimeManager(); - DataSourceVO dataSource = runtimeManager.getDataSource(idDs); - dataSource.setEnabled(false); - dataSource.setState(new StopChangeEnableStateDs()); - runtimeManager.saveDataSource(dataSource); - - } catch (Exception e) { - e.printStackTrace(); - } - - } -} diff --git a/src/org/scada_lts/ds/model/ReactivationDs.java b/src/org/scada_lts/ds/model/ReactivationDs.java new file mode 100644 index 0000000000..be1c61a579 --- /dev/null +++ b/src/org/scada_lts/ds/model/ReactivationDs.java @@ -0,0 +1,82 @@ +package org.scada_lts.ds.model; + +import java.io.Serializable; +import java.util.Objects; + +/** + * @autor grzegorz.bylica@gmail.com on 23.10.18 + * + * Associated with class in vuejs SleepAndReactivationDS.vue + */ +public class ReactivationDs implements Serializable { + + private static final long serialVersionUID = 8828977247133645961L; + + public static final short TYPE_OF_SLEEP_MINUTE = 0; + public static final short TYPE_OF_SLEEP_HOUR = 1; + public static final short TYPE_OF_SLEEP_DAY = 2; + + private boolean sleep; + private short type; + private short value; + + public ReactivationDs() { + this.sleep = false; + this.type = TYPE_OF_SLEEP_MINUTE; + this.value = 1; // 1 minute + } + + public ReactivationDs(boolean sleep, short type, short value) { + this.sleep = sleep; + this.type = type; + this.value = value; + } + + public boolean isSleep() { + return sleep; + } + + public void setSleep(boolean sleep) { + this.sleep = sleep; + } + + public short getType() { + return type; + } + + public void setType(short type) { + this.type = type; + } + + public short getValue() { + return value; + } + + public void setValue(short value) { + this.value = value; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ReactivationDs that = (ReactivationDs) o; + return sleep == that.sleep && + type == that.type && + value == that.value; + } + + @Override + public int hashCode() { + return Objects.hash(sleep, type, value); + } + + @Override + public String toString() { + return "ReactivationDs{" + + "sleep=" + sleep + + ", type=" + type + + ", value=" + value + + '}'; + } +} diff --git a/src/org/scada_lts/ds/reactivation/MenagerReactivation.java b/src/org/scada_lts/ds/reactivation/MenagerReactivation.java new file mode 100644 index 0000000000..d0a2b9b24e --- /dev/null +++ b/src/org/scada_lts/ds/reactivation/MenagerReactivation.java @@ -0,0 +1,114 @@ +package org.scada_lts.ds.reactivation; + +import com.serotonin.mango.vo.dataSource.DataSourceVO; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.quartz.*; +import org.quartz.impl.StdSchedulerFactory; +import org.quartz.utils.Key; +import org.scada_lts.ds.model.ReactivationDs; + +import java.util.AbstractMap; +import java.util.Date; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @autor grzegorz.bylica@gmail.com on 24.10.18 + */ +public class MenagerReactivation { + + private static final Log LOG = LogFactory.getLog(MenagerReactivation.class); + + private static final long MINUTE_IN_MILISECONDS = 60_000; + private static final long HOUR_IN_MILISECONDS = 3_600_000; + private static final long DAY_IN_MILISECONDS = 24 * HOUR_IN_MILISECONDS; + + private static final String EVENT_MESSAGE_OF_REACTIVATION = ""; + + private ConcurrentHashMap> sleepDsIndexJobName = new ConcurrentHashMap>(); + private ConcurrentHashMap sleepDsIndexIdDs = new ConcurrentHashMap<>(); + + private static final MenagerReactivation instance = new MenagerReactivation(); + private Scheduler scheduler; + + public MenagerReactivation() { + try { + this.scheduler = new StdSchedulerFactory().getScheduler(); + this.scheduler.start(); + } catch (SchedulerException e) { + LOG.error(e); + } + } + + public static MenagerReactivation getInstance() { + return instance; + } + + public void addProcess(StatefulJob sj, ReactivationDs rd, DataSourceVO vo) { + LOG.info("addProcess"); + + JobDetail job = new JobDetail(); + job.setName(sj.toString()); + job.setJobClass(sj.getClass()); + + AbstractMap.SimpleImmutableEntry dsInfo = new AbstractMap.SimpleImmutableEntry<>(vo.getName(), vo.getId()); + sleepDsIndexJobName.put(job.getKey().getName(), dsInfo); + sleepDsIndexIdDs.put(vo.getId(), job.getKey()); + + SimpleTrigger trigger = new SimpleTrigger(); + + Long interval = getAdditionalMilliseconds(rd); + Date startTime = new Date(System.currentTimeMillis() + interval ); + LOG.info("process will be start:" + startTime); + trigger.setStartTime(startTime); + trigger.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY); + + LOG.trace("Quartz - "+sj.getClass()+ " interval: " + interval); + trigger.setRepeatInterval(interval); + + trigger.setName("Quartz - trigger-"+sj.getClass()+""); + + try { + scheduler.scheduleJob(job, trigger); + } catch (SchedulerException e) { + LOG.error(e); + } + + } + + public Map.Entry getId(String keyNameJob) { + return sleepDsIndexJobName.get(keyNameJob); + } + + public void removeInfoAboutJob(String keyNameJob) { + + Map.Entry dsInfo = sleepDsIndexJobName.get(keyNameJob); + sleepDsIndexIdDs.remove(dsInfo.getValue()); + sleepDsIndexJobName.remove(keyNameJob); + } + + public long getTimeToNextFire(int idDs) { + + int ERROR = -1; + try { + Key key = sleepDsIndexIdDs.get(idDs); + return scheduler.getTriggersOfJob(key.getName(), key.getGroup())[0].getNextFireTime().getTime() - new Date().getTime(); + } catch (SchedulerException e) { + LOG.error(e); + } + return ERROR; + + } + + private long getAdditionalMilliseconds(ReactivationDs r) { + if (r.getType() == ReactivationDs.TYPE_OF_SLEEP_MINUTE) { + return r.getValue() * MINUTE_IN_MILISECONDS; + } else if (r.getType() == ReactivationDs.TYPE_OF_SLEEP_HOUR) { + return r.getValue() * HOUR_IN_MILISECONDS; + } else if (r.getType() == ReactivationDs.TYPE_OF_SLEEP_DAY){ + return r.getValue() * DAY_IN_MILISECONDS; + } + return 0; + } +} diff --git a/src/org/scada_lts/ds/reactivation/ReactivationConnectHttpRetriever.java b/src/org/scada_lts/ds/reactivation/ReactivationConnectHttpRetriever.java new file mode 100644 index 0000000000..c63207bc8b --- /dev/null +++ b/src/org/scada_lts/ds/reactivation/ReactivationConnectHttpRetriever.java @@ -0,0 +1,56 @@ +package org.scada_lts.ds.reactivation; + +import com.serotonin.mango.rt.dataSource.http.HttpRetrieverDataSourceRT; +import com.serotonin.mango.vo.dataSource.DataSourceVO; +import com.serotonin.mango.vo.dataSource.http.HttpRetrieverDataSourceVO; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.quartz.SchedulerException; +import org.quartz.StatefulJob; +import org.quartz.utils.Key; +import org.scada_lts.dao.DataSourceDAO; +import org.scada_lts.ds.StartStopDsRT; +import org.scada_lts.ds.state.StartSleepStateDs; + +import java.util.Map; + +/** + * @autor grzegorz.bylica@gmail.com on 24.10.18 + */ +public class ReactivationConnectHttpRetriever implements StatefulJob { + + private static final Log LOG = LogFactory.getLog(ReactivationConnectHttpRetriever.class); + + @Override + public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { + + Key keyJob = jobExecutionContext.getJobDetail().getKey(); + + Map.Entry entry = MenagerReactivation.getInstance().getId(keyJob.getName()); + int id = (int) entry.getValue(); + String name = (String) entry.getKey(); + + DataSourceDAO dao = new DataSourceDAO(); + DataSourceVO ds = dao.getDataSource(id); + + HttpRetrieverDataSourceVO hrds = (HttpRetrieverDataSourceVO) ds; + + if (HttpRetrieverDataSourceRT.testConnection(hrds.getUrl(), hrds.getTimeoutSeconds(), hrds.getRetries())) { + + try { + jobExecutionContext.getScheduler().deleteJob(keyJob.getName(), keyJob.getGroup()); + } catch (SchedulerException e) { + LOG.error(e); + } finally { + StartStopDsRT stopDsRT = new StartStopDsRT(id,true, new StartSleepStateDs()); + new Thread(stopDsRT).start(); + MenagerReactivation.getInstance().removeInfoAboutJob(keyJob.getName()); + } + } else { + // nothing to do + } + + } +} diff --git a/src/org/scada_lts/ds/state/SleepStateDs.java b/src/org/scada_lts/ds/state/SleepStateDs.java new file mode 100644 index 0000000000..d0044ea4f8 --- /dev/null +++ b/src/org/scada_lts/ds/state/SleepStateDs.java @@ -0,0 +1,19 @@ +package org.scada_lts.ds.state; + +import org.scada_lts.localization.ConfigLocalization; + +import java.io.Serializable; +import java.util.Locale; + +/** + * @autor grzegorz.bylica@gmail.com on 02.11.18 + */ +public class SleepStateDs implements IStateDs, Serializable { + + private static final String STOP_SLEEP = "ds.state.sleep"; + + @Override + public String getDescribe() { + return ConfigLocalization.getInstance().messageSource().getMessage(STOP_SLEEP, new Object[]{}, Locale.getDefault()); + } +} diff --git a/src/org/scada_lts/ds/state/StartSleepStateDs.java b/src/org/scada_lts/ds/state/StartSleepStateDs.java new file mode 100644 index 0000000000..714c5fa964 --- /dev/null +++ b/src/org/scada_lts/ds/state/StartSleepStateDs.java @@ -0,0 +1,20 @@ +package org.scada_lts.ds.state; + +import org.scada_lts.localization.ConfigLocalization; + +import java.io.Serializable; +import java.util.Locale; + +/** + * @autor grzegorz.bylica@gmail.com on 02.11.18 + */ +public class StartSleepStateDs implements IStateDs, Serializable { + + private static final String START_SLEEP = "ds.state.startSleep"; + + @Override + public String getDescribe() { + return ConfigLocalization.getInstance().messageSource().getMessage(START_SLEEP, new Object[]{}, Locale.getDefault()); + } + +} diff --git a/src/org/scada_lts/ds/state/change/AlertObserver.java b/src/org/scada_lts/ds/state/change/AlertObserver.java new file mode 100644 index 0000000000..caf5512e5f --- /dev/null +++ b/src/org/scada_lts/ds/state/change/AlertObserver.java @@ -0,0 +1,28 @@ +package org.scada_lts.ds.state.change; + +import com.serotonin.mango.rt.dataSource.http.HttpRetrieverDataSourceRT; +import com.serotonin.mango.vo.dataSource.DataSourceVO; +import org.scada_lts.ds.state.IStateDs; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +/** + * @autor grzegorz.bylica@gmail.com on 02.11.18 + */ +public class AlertObserver implements PropertyChangeListener { + + public AlertObserver(ChangeStatus changeManageStatus) { + changeManageStatus.addChangeListener(this); + } + + @Override + public void propertyChange(PropertyChangeEvent propertyChangeEvent) { + + String describe = ((IStateDs) propertyChangeEvent.getNewValue()).getDescribe(); + DataSourceVO vo = (DataSourceVO) propertyChangeEvent.getSource(); + + HttpRetrieverDataSourceRT.raiseEvent(describe, vo); + + } +} diff --git a/src/org/scada_lts/ds/state/change/ChangeStatus.java b/src/org/scada_lts/ds/state/change/ChangeStatus.java new file mode 100644 index 0000000000..085276c2c8 --- /dev/null +++ b/src/org/scada_lts/ds/state/change/ChangeStatus.java @@ -0,0 +1,33 @@ +package org.scada_lts.ds.state.change; + +import org.scada_lts.ds.state.IStateDs; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.List; + +/** + * @autor grzegorz.bylica@gmail.com on 02.11.18 + */ +public class ChangeStatus { + + private static final String STATE_PROPERTY = "state_property"; + + List listener; + + protected ChangeStatus() { + listener = new ArrayList<>(); + } + + protected void notifyListeners(Object object, IStateDs oldValue, IStateDs newValue) { + for (PropertyChangeListener state : listener) { + state.propertyChange(new PropertyChangeEvent(object, STATE_PROPERTY, oldValue, newValue)); + } + } + + public void addChangeListener(PropertyChangeListener newListener) { + listener.add(newListener); + } + +} diff --git a/src/org/scada_lts/web/mvc/api/ReactivationDsAPI.java b/src/org/scada_lts/web/mvc/api/ReactivationDsAPI.java new file mode 100644 index 0000000000..b20e73d715 --- /dev/null +++ b/src/org/scada_lts/web/mvc/api/ReactivationDsAPI.java @@ -0,0 +1,41 @@ +package org.scada_lts.web.mvc.api; + +import com.serotonin.mango.Common; +import com.serotonin.mango.vo.User; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.scada_lts.ds.reactivation.MenagerReactivation; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import javax.servlet.http.HttpServletRequest; + +/** + * @autor grzegorz.bylica@gmail.com on 08.11.18 + */ +@Controller +public class ReactivationDsAPI { + + private static final Log LOG = LogFactory.getLog(ReactivationDsAPI.class); + + @RequestMapping(value = "/api/check-reactivation/{idDs}", method = RequestMethod.GET) + public ResponseEntity checkReactivation(@PathVariable(name="idDs") int idDs, HttpServletRequest request) { + + LOG.info("/api/check-reactivation/{idDs} idDs:" + idDs); + try { + User user = Common.getUser(request); + if (user != null && user.isAdmin()) { + long time = MenagerReactivation.getInstance().getTimeToNextFire(idDs); + return new ResponseEntity(""+time, HttpStatus.OK); + } else { + return new ResponseEntity(HttpStatus.UNAUTHORIZED); + } + } catch (Exception e) { + return new ResponseEntity(e.toString(), HttpStatus.INTERNAL_SERVER_ERROR); + } + } +}