Merge branch 'master' of https://repository.entgra.net/community/device-mgt-core into live-chat-feature

pull/1/head
Thashmi-nil 2 years ago
commit 0f6db69c18

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>grafana-mgt</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>grafana-mgt</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>grafana-mgt</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>analytics-mgt</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -3,7 +3,7 @@
<parent>
<artifactId>carbon-devicemgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -3,7 +3,7 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

@ -3,7 +3,7 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -20,7 +20,7 @@
<parent>
<artifactId>application-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>application-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>application-mgt</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>application-mgt</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -94,6 +94,7 @@ public class SQLServerApplicationDAOImpl extends GenericApplicationDAOImpl {
|| StringUtils.isNotEmpty(filter.getAppReleaseType())) {
sql += "LEFT JOIN AP_APP_RELEASE ON AP_APP.ID = AP_APP_RELEASE.AP_APP_ID ";
}
sql += "WHERE AP_APP.TENANT_ID = ? ";
if (StringUtils.isNotEmpty(filter.getAppType()) && !Constants.ALL.equalsIgnoreCase(filter.getAppType())) {
sql += "AND AP_APP.TYPE = ? ";
}
@ -128,7 +129,7 @@ public class SQLServerApplicationDAOImpl extends GenericApplicationDAOImpl {
sql += filter.getSortBy() +" ";
}
if (filter.getLimit() != -1) {
sql += "ORDER BY ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY ";
sql += "OFFSET ? ROWS FETCH NEXT ? ROWS ONLY ";
}
sql += ") AS app_data ON app_data.ID = AP_APP.ID "
+ "LEFT JOIN ("
@ -145,6 +146,7 @@ public class SQLServerApplicationDAOImpl extends GenericApplicationDAOImpl {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
int paramIndex = 1;
stmt.setInt(paramIndex++, tenantId);
if (StringUtils.isNotEmpty(filter.getAppType()) && !Constants.ALL.equalsIgnoreCase(filter.getAppType())) {
stmt.setString(paramIndex++, filter.getAppType());
}

@ -22,7 +22,7 @@
<parent>
<artifactId>application-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>application-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>certificate-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>certificate-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -38,7 +38,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>certificate-mgt</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -23,7 +23,7 @@
<parent>
<artifactId>device-mgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -23,7 +23,7 @@
<parent>
<artifactId>device-mgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>carbon-devicemgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<artifactId>device-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>device-mgt</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -103,6 +103,7 @@
org.wso2.carbon.ndatasource.core,
org.wso2.carbon.ntask.core.*,
org.wso2.carbon.ntask.common,
io.entgra.task.mgt.common.*,
org.apache.commons.collections;version="${commons-collections.version.range}",
org.wso2.carbon.email.sender.*,
io.swagger.annotations.*;resolution:=optional,
@ -347,6 +348,10 @@
<artifactId>okhttp</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.task.mgt.common</artifactId>
</dependency>
</dependencies>
</project>

@ -409,7 +409,7 @@ public class DeviceInformationManagerImpl implements DeviceInformationManager {
}
if (!HttpReportingUtil.isTrackerEnabled()) {
if (log.isDebugEnabled()) {
log.info("Traccar is disabled");
log.debug("Traccar is disabled");
}
}
}
@ -473,7 +473,7 @@ public class DeviceInformationManagerImpl implements DeviceInformationManager {
}
if (!HttpReportingUtil.isTrackerEnabled()) {
if (log.isDebugEnabled()) {
log.info("Traccar is disabled");
log.debug("Traccar is disabled");
}
}
}

@ -32,31 +32,10 @@ import org.wso2.carbon.device.mgt.core.task.impl.DynamicPartitionedScheduleTask;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class OperationTimeoutTask extends DynamicPartitionedScheduleTask {
private static final Log log = LogFactory.getLog(OperationTimeoutTask.class);
private OperationTimeout operationTimeoutConfig;
@Override
public void setProperties(Map<String, String> properties) {
super.setProperties(properties);
String operationTimeoutTaskConfigStr = properties
.get(OperationTimeoutTaskManagerServiceImpl.OPERATION_TIMEOUT_TASK_CONFIG);
Gson gson = new Gson();
operationTimeoutConfig = gson.fromJson(operationTimeoutTaskConfigStr, OperationTimeout.class);
}
@Override
public String getProperty(String name) {
return super.getProperty(name);
}
@Override
public void refreshContext() {
super.refreshContext();
}
@Override
protected void setup() {
@ -65,12 +44,15 @@ public class OperationTimeoutTask extends DynamicPartitionedScheduleTask {
@Override
protected void executeDynamicTask() {
String operationTimeoutTaskConfigStr = getProperty(
OperationTimeoutTaskManagerServiceImpl.OPERATION_TIMEOUT_TASK_CONFIG);
Gson gson = new Gson();
OperationTimeout operationTimeoutConfig = gson.fromJson(operationTimeoutTaskConfigStr, OperationTimeout.class);
try {
long timeMillis = System.currentTimeMillis() - operationTimeoutConfig.getTimeout() * 60 * 1000;
List<String> deviceTypes = new ArrayList<>();
if (operationTimeoutConfig.getDeviceTypes().size() == 1 &&
"ALL".equals(operationTimeoutConfig.getDeviceTypes().get( 0))) {
"ALL".equals(operationTimeoutConfig.getDeviceTypes().get(0))) {
try {
List<DeviceType> deviceTypeList = DeviceManagementDataHolder.getInstance()
.getDeviceManagementProvider().getDeviceTypes();

@ -444,7 +444,9 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
//Exception was not thrown due to being conflicted with non-traccar features
}
} else {
log.info("Traccar is disabled");
if (log.isDebugEnabled()) {
log.debug("Traccar is disabled");
}
}
//enroll Traccar device
@ -544,7 +546,9 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
//Exception was not thrown due to being conflicted with non-traccar features
}
} else {
log.info("Traccar is disabled");
if (log.isDebugEnabled()) {
log.debug("Traccar is disabled");
}
}
//enroll Traccar device
return status;

@ -37,7 +37,6 @@ import org.wso2.carbon.device.mgt.core.task.impl.DynamicPartitionedScheduleTask;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* This implements the Task service which monitors the device activity periodically & update the device-status if
@ -47,19 +46,8 @@ public class DeviceStatusMonitoringTask extends DynamicPartitionedScheduleTask {
private static final Log log = LogFactory.getLog(DeviceStatusMonitoringTask.class);
private String deviceType;
private DeviceStatusTaskPluginConfig deviceStatusTaskPluginConfig;
private int deviceTypeId = -1;
@Override
public void setProperties(Map<String, String> properties) {
super.setProperties(properties);
deviceType = properties.get(DeviceStatusTaskManagerServiceImpl.DEVICE_TYPE);
deviceTypeId = Integer.parseInt(properties.get(DeviceStatusTaskManagerServiceImpl.DEVICE_TYPE_ID));
String deviceStatusTaskConfigStr = properties.get(DeviceStatusTaskManagerServiceImpl.DEVICE_STATUS_TASK_CONFIG);
Gson gson = new Gson();
deviceStatusTaskPluginConfig = gson.fromJson(deviceStatusTaskConfigStr, DeviceStatusTaskPluginConfig.class);
}
@Override
protected void setup() {
}
@ -92,6 +80,11 @@ public class DeviceStatusMonitoringTask extends DynamicPartitionedScheduleTask {
@Override
public void executeDynamicTask() {
deviceType = getProperty(DeviceStatusTaskManagerServiceImpl.DEVICE_TYPE);
deviceTypeId = Integer.parseInt(getProperty(DeviceStatusTaskManagerServiceImpl.DEVICE_TYPE_ID));
String deviceStatusTaskConfigStr = getProperty(DeviceStatusTaskManagerServiceImpl.DEVICE_STATUS_TASK_CONFIG);
Gson gson = new Gson();
DeviceStatusTaskPluginConfig deviceStatusTaskPluginConfig = gson.fromJson(deviceStatusTaskConfigStr, DeviceStatusTaskPluginConfig.class);
try {
List<EnrolmentInfo> enrolmentInfoTobeUpdated = new ArrayList<>();
List<DeviceMonitoringData> allDevicesForMonitoring = getAllDevicesForMonitoring();
@ -102,10 +95,10 @@ public class DeviceStatusMonitoringTask extends DynamicPartitionedScheduleTask {
EnrolmentInfo enrolmentInfo = monitoringData.getDevice().getEnrolmentInfo();
EnrolmentInfo.Status status = null;
if (lastUpdatedTime >= this.deviceStatusTaskPluginConfig
if (lastUpdatedTime >= deviceStatusTaskPluginConfig
.getIdleTimeToMarkInactive()) {
status = EnrolmentInfo.Status.INACTIVE;
} else if (lastUpdatedTime >= this.deviceStatusTaskPluginConfig
} else if (lastUpdatedTime >= deviceStatusTaskPluginConfig
.getIdleTimeToMarkUnreachable()) {
status = EnrolmentInfo.Status.UNREACHABLE;
}

@ -48,7 +48,6 @@ import org.wso2.carbon.device.mgt.core.task.DeviceMgtTaskException;
import org.wso2.carbon.device.mgt.core.task.DeviceTaskManager;
import java.util.List;
import java.util.Map;
public class DeviceDetailsRetrieverTask extends DynamicPartitionedScheduleTask {
@ -56,14 +55,9 @@ public class DeviceDetailsRetrieverTask extends DynamicPartitionedScheduleTask {
private String deviceType;
private DeviceManagementProviderService deviceManagementProviderService;
@Override
public void setProperties(Map<String, String> map) {
super.setProperties(map);
deviceType = map.get("DEVICE_TYPE");
}
@Override
public void executeDynamicTask() {
deviceType = getProperty("DEVICE_TYPE");
deviceManagementProviderService = DeviceManagementDataHolder.getInstance()
.getDeviceManagementProvider();
OperationMonitoringTaskConfig operationMonitoringTaskConfig = deviceManagementProviderService

@ -19,10 +19,11 @@
package org.wso2.carbon.device.mgt.core.task.impl;
import io.entgra.server.bootup.heartbeat.beacon.exception.HeartBeatManagementException;
import io.entgra.task.mgt.common.constant.TaskMgtConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.common.ServerCtxInfo;
import org.wso2.carbon.device.mgt.common.DynamicTaskContext;
import org.wso2.carbon.device.mgt.common.ServerCtxInfo;
import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder;
import org.wso2.carbon.ntask.core.Task;
@ -37,11 +38,11 @@ public abstract class DynamicPartitionedScheduleTask implements Task {
private Map<String, String> properties;
@Override
public void setProperties(Map<String, String> properties) {
public final void setProperties(Map<String, String> properties) {
this.properties = properties;
}
public String getProperty(String name) {
public final String getProperty(String name) {
if (properties == null) {
return null;
}
@ -62,7 +63,7 @@ public abstract class DynamicPartitionedScheduleTask implements Task {
}
}
} catch (HeartBeatManagementException e) {
log.error("Error Instantiating Variables necessary for Dynamic Task Scheduling. Dynamic Tasks will not function." , e);
log.error("Error Instantiating Variables necessary for Dynamic Task Scheduling. Dynamic Tasks will not function.", e);
}
setup();
}
@ -70,11 +71,41 @@ public abstract class DynamicPartitionedScheduleTask implements Task {
@Override
public final void execute() {
refreshContext();
executeDynamicTask();
if (taskContext != null && taskContext.isPartitioningEnabled()) {
String localHashIndex = getProperty(TaskMgtConstants.Task.LOCAL_HASH_INDEX);
// These tasks are not dynamically scheduled. They are added via a config so scheduled in each node
// during the server startup
if (localHashIndex == null ) {
if (log.isDebugEnabled()) {
log.debug("Executing startup scheduled task (" + getTaskName() + ") with class: " +
this.getClass().getName());
}
executeDynamicTask();
return;
}
if (localHashIndex.equals(String.valueOf(taskContext.getServerHashIndex()))) {
if (log.isDebugEnabled()) {
log.debug("Executing dynamically scheduled task (" + getTaskName() +
") for current server hash index: " + localHashIndex);
}
executeDynamicTask();
} else {
if (log.isDebugEnabled()) {
log.debug("Ignoring execution of task (" + getTaskName() +
") not belonging to current serer hash index: " + localHashIndex);
}
}
} else {
executeDynamicTask();
}
}
public String getTaskName() {
return getProperty(TaskMgtConstants.Task.LOCAL_TASK_NAME);
}
public void refreshContext(){
if(taskContext != null && taskContext.isPartitioningEnabled()) {
public void refreshContext() {
if (taskContext != null && taskContext.isPartitioningEnabled()) {
try {
updateContext();
} catch (HeartBeatManagementException e) {

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -23,7 +23,7 @@
<parent>
<artifactId>device-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>heartbeat-management</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -19,13 +19,14 @@
package io.entgra.server.bootup.heartbeat.beacon.dto;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
public class ElectedCandidate {
private String serverUUID;
private Timestamp timeOfElection;
private List<String> acknowledgedTaskList = null;
private List<String> acknowledgedTaskList = new ArrayList<>();
public List<String> getAcknowledgedTaskList() {
return acknowledgedTaskList;

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>identity-extensions</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>identity-extensions</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -3,7 +3,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>policy-mgt</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -3,7 +3,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>policy-mgt</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>policy-mgt</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>policy-mgt</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -23,7 +23,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
~
~ Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
~ Version 2.0 (the "License"); you may not use this file except
~ in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>task-mgt</artifactId>
<packaging>pom</packaging>
<name>Entgra IoT - Task Management Component</name>
<url>http://entgra.io</url>
<modules>
<module>task-manager</module>
<module>task-watcher</module>
</modules>
</project>

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
~
~ Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
~ Version 2.0 (the "License"); you may not use this file except
~ in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>task-manager</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>io.entgra.task.mgt.common</artifactId>
<packaging>bundle</packaging>
<name>Entgra IoT - Task Management Common</name>
<description>Entgra IoT - Task Management Common</description>
<url>https://entgra.io</url>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Bundle-Version>${carbon.device.mgt.version}</Bundle-Version>
<Bundle-Description>Task Management Common Bundle</Bundle-Description>
<Export-Package>
io.entgra.task.mgt.common.*
</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,88 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.common.bean;
import java.util.Map;
public class DynamicTask {
private int dynamicTaskId;
private String name;
private String cronExpression;
private boolean isEnabled;
private int tenantId;
private String taskClassName;
private Map<String, String> properties;
public int getDynamicTaskId() {
return dynamicTaskId;
}
public void setDynamicTaskId(int dynamicTaskId) {
this.dynamicTaskId = dynamicTaskId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCronExpression() {
return cronExpression;
}
public void setCronExpression(String cronExpression) {
this.cronExpression = cronExpression;
}
public boolean isEnabled() {
return isEnabled;
}
public void setEnabled(boolean enable) {
isEnabled = enable;
}
public int getTenantId() {
return tenantId;
}
public void setTenantId(int tenantId) {
this.tenantId = tenantId;
}
public String getTaskClassName() {
return taskClassName;
}
public void setTaskClassName(String taskClassName) {
this.taskClassName = taskClassName;
}
public Map<String, String> getProperties() {
return properties;
}
public void setProperties(Map<String, String> properties) {
this.properties = properties;
}
}

@ -0,0 +1,53 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.common.constant;
public class TaskMgtConstants {
public static final class DataSourceProperties {
private DataSourceProperties() {
throw new AssertionError();
}
public static final String DB_CHECK_QUERY = "SELECT * FROM DM_DEVICE";
public static final String TASK_CONFIG_XML_NAME = "task-mgt-config.xml";
}
public static final class DataBaseTypes {
private DataBaseTypes() {
throw new AssertionError();
}
public static final String DB_TYPE_MYSQL = "MySQL";
public static final String DB_TYPE_ORACLE = "Oracle";
public static final String DB_TYPE_MSSQL = "Microsoft SQL Server";
public static final String DB_TYPE_DB2 = "DB2";
public static final String DB_TYPE_H2 = "H2";
public static final String DB_TYPE_POSTGRESQL = "PostgreSQL";
}
public static final class Task {
public static final String DYNAMIC_TASK_TYPE = "DYNAMIC_TASK";
public static final String NAME_SEPARATOR = "_";
public static final String PROPERTY_KEY_COLUMN_NAME = "PROPERTY_NAME";
public static final String PROPERTY_VALUE_COLUMN_NAME = "PROPERTY_VALUE";
public static final String TENANT_ID_PROP = "__TENANT_ID_PROP__";
public static final String LOCAL_HASH_INDEX = "__LOCAL_HASH_INDEX__";
public static final String LOCAL_TASK_NAME = "__LOCAL_TASK_NAME__";
}
}

@ -0,0 +1,44 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.common.exception;
public class IllegalTransactionStateException extends RuntimeException {
private static final long serialVersionUID = -3151279331929070297L;
public IllegalTransactionStateException(String msg, Exception nestedEx) {
super(msg, nestedEx);
}
public IllegalTransactionStateException(String message, Throwable cause) {
super(message, cause);
}
public IllegalTransactionStateException(String msg) {
super(msg);
}
public IllegalTransactionStateException() {
super();
}
public IllegalTransactionStateException(Throwable cause) {
super(cause);
}
}

@ -0,0 +1,31 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.common.exception;
public class TaskManagementDAOException extends Exception {
public TaskManagementDAOException(String msg) {
super(msg);
}
public TaskManagementDAOException(String msg, Exception e) {
super(msg, e);
}
}

@ -0,0 +1,29 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.common.exception;
public class TaskManagementException extends Exception {
public TaskManagementException(String msg) {
super(msg);
}
public TaskManagementException(String msg, Exception e) {
super(msg, e);
}
}

@ -0,0 +1,33 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.common.exception;
/**
* Represents the exception thrown during validating the request.
*/
public class TaskNotFoundException extends Exception {
public TaskNotFoundException(String message) {
super(message);
}
public TaskNotFoundException(String message, Exception ex) {
super(message, ex);
}
}

@ -0,0 +1,44 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.common.exception;
public class TransactionManagementException extends Exception {
private static final long serialVersionUID = -3151279321929070297L;
public TransactionManagementException(String msg, Exception nestedEx) {
super(msg, nestedEx);
}
public TransactionManagementException(String message, Throwable cause) {
super(message, cause);
}
public TransactionManagementException(String msg) {
super(msg);
}
public TransactionManagementException() {
super();
}
public TransactionManagementException(Throwable cause) {
super(cause);
}
}

@ -0,0 +1,47 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.common.exception;
/**
* This runtime exception will be thrown if the server has configured with unsupported DB engine.
*/
public class UnsupportedDatabaseEngineException extends RuntimeException {
private static final long serialVersionUID = -3151279311929070297L;
public UnsupportedDatabaseEngineException(String msg, Exception nestedEx) {
super(msg, nestedEx);
}
public UnsupportedDatabaseEngineException(String message, Throwable cause) {
super(message, cause);
}
public UnsupportedDatabaseEngineException(String msg) {
super(msg);
}
public UnsupportedDatabaseEngineException() {
super();
}
public UnsupportedDatabaseEngineException(Throwable cause) {
super(cause);
}
}

@ -0,0 +1,43 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.common.spi;
import io.entgra.task.mgt.common.exception.TaskNotFoundException;
import io.entgra.task.mgt.common.exception.TaskManagementException;
import io.entgra.task.mgt.common.bean.DynamicTask;
import java.util.List;
public interface TaskManagementService {
void init() throws TaskManagementException;
void createTask(DynamicTask dynamicTask) throws TaskManagementException;
void updateTask(int dynamicTaskId, DynamicTask dynamicTask) throws TaskManagementException, TaskNotFoundException;
void toggleTask(int dynamicTaskId, boolean isEnabled) throws TaskManagementException, TaskNotFoundException;
void deleteTask(int dynamicTaskId) throws TaskManagementException, TaskNotFoundException;
List<DynamicTask> getAllDynamicTasks() throws TaskManagementException;
DynamicTask getDynamicTaskById(int dynamicTaskId) throws TaskManagementException;
List<DynamicTask> getActiveDynamicTasks() throws TaskManagementException;
}

@ -0,0 +1,141 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
~
~ Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
~ Version 2.0 (the "License"); you may not use this file except
~ in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>task-manager</artifactId>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>io.entgra.task.mgt.core</artifactId>
<packaging>bundle</packaging>
<name>Entgra IoT - Task manager Core</name>
<description>Entgra IoT - Task manager Core</description>
<url>http://entgra.io</url>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Bundle-Version>${carbon.device.mgt.version}</Bundle-Version>
<Bundle-Description>Task Management Core Bundle</Bundle-Description>
<Private-Package>io.entgra.task.mgt.core.internal</Private-Package>
<Import-Package>
org.osgi.framework.*;version="${imp.package.version.osgi.framework}",
org.osgi.service.*;version="${imp.package.version.osgi.service}",
org.apache.commons.logging,
org.wso2.carbon.ndatasource.core,
org.w3c.dom,
javax.xml.bind.annotation,
javax.xml.bind,
javax.sql,
javax.naming,
io.entgra.task.mgt.common.*,
org.wso2.carbon.utils.*,
org.wso2.carbon.ntask.core.*,
org.wso2.carbon.ntask.common,
org.wso2.carbon.device.mgt.common.*,
org.wso2.carbon.context,
org.apache.commons.codec.binary;version="${commons-codec.wso2.osgi.version.range}",
org.apache.commons.codec.digest;version="${commons-codec.wso2.osgi.version.range}",
io.entgra.server.bootup.heartbeat.beacon.dto,
io.entgra.server.bootup.heartbeat.beacon.exception,
io.entgra.server.bootup.heartbeat.beacon.service,
</Import-Package>
<Export-Package>
!io.entgra.task.mgt.core.internal,
io.entgra.task.mgt.core.*
</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.services</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.ndatasource.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.task.mgt.common</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.utils</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-codec.wso2</groupId>
<artifactId>commons-codec</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.common</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.server.bootup.heartbeat.beacon</artifactId>
<scope>provided</scope>
</dependency>
<!--nTask dependencies-->
<dependency>
<groupId>org.wso2.carbon.commons</groupId>
<artifactId>org.wso2.carbon.ntask.core</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

@ -0,0 +1,79 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.core.config;
import io.entgra.task.mgt.common.constant.TaskMgtConstants;
import io.entgra.task.mgt.common.exception.TaskManagementException;
import io.entgra.task.mgt.core.util.TaskManagementUtil;
import org.w3c.dom.Document;
import org.wso2.carbon.utils.CarbonUtils;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.File;
/**
* Class responsible for the task mgt configuration initialization.
*/
public class TaskConfigurationManager {
private TaskManagementConfig taskManagementConfig;
private static volatile TaskConfigurationManager taskConfigurationManager;
private static final String TASK_MGT_CONFIG_PATH =
CarbonUtils.getCarbonConfigDirPath() + File.separator +
TaskMgtConstants.DataSourceProperties.TASK_CONFIG_XML_NAME;
public static TaskConfigurationManager getInstance() {
if (taskConfigurationManager == null) {
synchronized (TaskConfigurationManager.class) {
if (taskConfigurationManager == null) {
taskConfigurationManager = new TaskConfigurationManager();
}
}
}
return taskConfigurationManager;
}
public synchronized void initConfig() throws TaskManagementException {
try {
File taskMgtConfig = new File(TASK_MGT_CONFIG_PATH);
Document doc = TaskManagementUtil.convertToDocument(taskMgtConfig);
/* Un-marshaling Device Management configuration */
JAXBContext cdmContext = JAXBContext.newInstance(TaskManagementConfig.class);
Unmarshaller unmarshaller = cdmContext.createUnmarshaller();
//unmarshaller.setSchema(getSchema());
this.taskManagementConfig = (TaskManagementConfig) unmarshaller.unmarshal(doc);
} catch (JAXBException e) {
throw new TaskManagementException("Error occurred while initializing Data Source config", e);
}
}
public TaskManagementConfig getTaskManagementConfig() throws TaskManagementException {
if (taskManagementConfig == null) {
initConfig();
}
return taskManagementConfig;
}
public void setTaskManagementConfig(TaskManagementConfig taskManagementConfig) {
this.taskManagementConfig = taskManagementConfig;
}
}

@ -0,0 +1,51 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.core.config;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* Represents Task Mgt configuration.
*/
@XmlRootElement(name = "TaskMgtConfiguration")
@SuppressWarnings("unused")
public final class TaskManagementConfig {
private TaskManagementConfigRepository taskMgtConfigRepository;
private boolean isTaskWatcherEnabled;
@XmlElement(name = "ManagementRepository", required = true)
public TaskManagementConfigRepository getTaskMgtConfigRepository() {
return taskMgtConfigRepository;
}
public void setTaskMgtConfigRepository(TaskManagementConfigRepository taskMgtConfigRepository) {
this.taskMgtConfigRepository = taskMgtConfigRepository;
}
@XmlElement(name = "TaskWatcherEnable", required = true)
public boolean isTaskWatcherEnabled() {
return isTaskWatcherEnabled;
}
public void setTaskWatcherEnabled(boolean enabled) {
this.isTaskWatcherEnabled = enabled;
}
}

@ -0,0 +1,42 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.core.config;
import io.entgra.task.mgt.core.config.datasource.DataSourceConfig;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* Class for holding management repository data.
*/
@XmlRootElement(name = "ManagementRepository")
public class TaskManagementConfigRepository {
private DataSourceConfig dataSourceConfig;
@XmlElement(name = "DataSourceConfiguration", required = true)
public DataSourceConfig getDataSourceConfig() {
return dataSourceConfig;
}
public void setDataSourceConfig(DataSourceConfig dataSourceConfig) {
this.dataSourceConfig = dataSourceConfig;
}
}

@ -0,0 +1,40 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.core.config.datasource;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* Class for holding data source configuration in task-mgt-config.xml at parsing with JAXB.
*/
@XmlRootElement(name = "DataSourceConfiguration")
public class DataSourceConfig {
private JNDILookupDefinition jndiLookupDefinition;
@XmlElement(name = "JndiLookupDefinition", required = true)
public JNDILookupDefinition getJndiLookupDefinition() {
return jndiLookupDefinition;
}
public void setJndiLookupDefinition(JNDILookupDefinition jndiLookupDefinition) {
this.jndiLookupDefinition = jndiLookupDefinition;
}
}

@ -0,0 +1,79 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.core.config.datasource;
import javax.xml.bind.annotation.*;
import java.util.List;
/**
* Class for hold JndiLookupDefinition of task-mgt-config.xml at parsing with JAXB.
*/
@XmlRootElement(name = "JndiLookupDefinition")
public class JNDILookupDefinition {
private String jndiName;
private List<JNDIProperty> jndiProperties;
@XmlElement(name = "Name", required = false)
public String getJndiName() {
return jndiName;
}
public void setJndiName(String jndiName) {
this.jndiName = jndiName;
}
@XmlElementWrapper(name = "Environment", required = false)
@XmlElement(name = "Property", nillable = false)
public List<JNDIProperty> getJndiProperties() {
return jndiProperties;
}
public void setJndiProperties(List<JNDIProperty> jndiProperties) {
this.jndiProperties = jndiProperties;
}
@XmlRootElement(name = "Property")
public static class JNDIProperty {
private String name;
private String value;
@XmlAttribute(name = "Name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlValue
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}

@ -0,0 +1,42 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.core.dao;
import io.entgra.task.mgt.common.bean.DynamicTask;
import io.entgra.task.mgt.common.exception.TaskManagementDAOException;
import java.util.List;
/**
* This class represents the key operations associated with dynamic tasks.
*/
public interface DynamicTaskDAO {
int addTask(DynamicTask dynamicTask) throws TaskManagementDAOException;
boolean updateDynamicTask(DynamicTask dynamicTask) throws TaskManagementDAOException;
void deleteDynamicTask(int dynamicTaskId) throws TaskManagementDAOException;
DynamicTask getDynamicTaskById(int dynamicTaskId) throws TaskManagementDAOException;
List<DynamicTask> getAllDynamicTasks() throws TaskManagementDAOException;
List<DynamicTask> getActiveDynamicTasks() throws TaskManagementDAOException;
}

@ -0,0 +1,35 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.core.dao;
import io.entgra.task.mgt.common.exception.TaskManagementDAOException;
import java.util.Map;
/**
* This class represents the key operations associated with dynamic task properties.
*/
public interface DynamicTaskPropDAO {
void addTaskProperties(int dynamicTaskId, Map<String, String> properties) throws TaskManagementDAOException;
Map<String, String> getDynamicTaskProps(int dynamicTaskId) throws TaskManagementDAOException;
void updateDynamicTaskProps(int dynamicTaskId, Map<String, String> properties)
throws TaskManagementDAOException;
}

@ -0,0 +1,206 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.core.dao.common;
import io.entgra.task.mgt.common.constant.TaskMgtConstants;
import io.entgra.task.mgt.common.exception.IllegalTransactionStateException;
import io.entgra.task.mgt.common.exception.TransactionManagementException;
import io.entgra.task.mgt.common.exception.UnsupportedDatabaseEngineException;
import io.entgra.task.mgt.core.config.datasource.DataSourceConfig;
import io.entgra.task.mgt.core.config.datasource.JNDILookupDefinition;
import io.entgra.task.mgt.core.dao.DynamicTaskDAO;
import io.entgra.task.mgt.core.dao.DynamicTaskPropDAO;
import io.entgra.task.mgt.core.dao.impl.DynamicTaskDAOImpl;
import io.entgra.task.mgt.core.dao.impl.DynamicTaskPropDAOImpl;
import io.entgra.task.mgt.core.dao.util.TaskManagementDAOUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Hashtable;
import java.util.List;
public class TaskManagementDAOFactory {
private static DataSource dataSource;
private static String databaseEngine;
private static final Log log = LogFactory.getLog(TaskManagementDAOFactory.class);
private static ThreadLocal<Connection> currentConnection = new ThreadLocal<>();
public static DynamicTaskDAO getDynamicTaskDAO() {
if (databaseEngine != null) {
switch (databaseEngine) {
case TaskMgtConstants.DataBaseTypes.DB_TYPE_H2:
case TaskMgtConstants.DataBaseTypes.DB_TYPE_MYSQL:
return new DynamicTaskDAOImpl();
default:
throw new UnsupportedDatabaseEngineException("Unsupported database engine : " + databaseEngine);
}
}
throw new IllegalStateException("Database engine has not initialized properly.");
}
public static DynamicTaskPropDAO getDynamicTaskPropDAO() {
if (databaseEngine != null) {
switch (databaseEngine) {
case TaskMgtConstants.DataBaseTypes.DB_TYPE_H2:
case TaskMgtConstants.DataBaseTypes.DB_TYPE_MYSQL:
return new DynamicTaskPropDAOImpl();
default:
throw new UnsupportedDatabaseEngineException("Unsupported database engine : " + databaseEngine);
}
}
throw new IllegalStateException("Database engine has not initialized properly.");
}
public static void init(DataSourceConfig config) {
dataSource = resolveDataSource(config);
try {
databaseEngine = dataSource.getConnection().getMetaData().getDatabaseProductName();
} catch (SQLException e) {
log.error("Error occurred while retrieving config.datasource connection", e);
}
}
public static void init(DataSource dtSource) {
dataSource = dtSource;
try {
databaseEngine = dataSource.getConnection().getMetaData().getDatabaseProductName();
} catch (SQLException e) {
log.error("Error occurred while retrieving config.datasource connection", e);
}
}
public static void beginTransaction() throws TransactionManagementException {
Connection conn = currentConnection.get();
if (conn != null) {
throw new IllegalTransactionStateException("A transaction is already active within the context of " +
"this particular thread. Therefore, calling 'beginTransaction/openConnection' while another " +
"transaction is already active is a sign of improper transaction handling");
}
try {
conn = dataSource.getConnection();
conn.setAutoCommit(false);
currentConnection.set(conn);
} catch (SQLException e) {
throw new TransactionManagementException("Error occurred while retrieving config.datasource connection", e);
}
}
public static void openConnection() throws SQLException {
Connection conn = currentConnection.get();
if (conn != null) {
throw new IllegalTransactionStateException("A transaction is already active within the context of " +
"this particular thread. Therefore, calling 'beginTransaction/openConnection' while another " +
"transaction is already active is a sign of improper transaction handling");
}
conn = dataSource.getConnection();
currentConnection.set(conn);
}
public static Connection getConnection() throws SQLException {
Connection conn = currentConnection.get();
if (conn == null) {
throw new IllegalTransactionStateException("No connection is associated with the current transaction. " +
"This might have ideally been caused by not properly initiating the transaction via " +
"'beginTransaction'/'openConnection' methods");
}
return conn;
}
public static void commitTransaction() {
Connection conn = currentConnection.get();
if (conn == null) {
throw new IllegalTransactionStateException("No connection is associated with the current transaction. " +
"This might have ideally been caused by not properly initiating the transaction via " +
"'beginTransaction'/'openConnection' methods");
}
try {
conn.commit();
} catch (SQLException e) {
log.error("Error occurred while committing the transaction", e);
}
}
public static void rollbackTransaction() {
Connection conn = currentConnection.get();
if (conn == null) {
throw new IllegalTransactionStateException("No connection is associated with the current transaction. " +
"This might have ideally been caused by not properly initiating the transaction via " +
"'beginTransaction'/'openConnection' methods");
}
try {
conn.rollback();
} catch (SQLException e) {
log.warn("Error occurred while roll-backing the transaction", e);
}
}
public static void closeConnection() {
Connection conn = currentConnection.get();
if (conn == null) {
throw new IllegalTransactionStateException("No connection is associated with the current transaction. " +
"This might have ideally been caused by not properly initiating the transaction via " +
"'beginTransaction'/'openConnection' methods");
}
try {
conn.close();
} catch (SQLException e) {
log.warn("Error occurred while close the connection");
}
currentConnection.remove();
}
/**
* Resolve data source from the data source definition
*
* @param config data source configuration
* @return data source resolved from the data source definition
*/
private static DataSource resolveDataSource(DataSourceConfig config) {
DataSource dataSource = null;
if (config == null) {
throw new RuntimeException(
"Device Management Repository data source configuration " + "is null and " +
"thus, is not initialized");
}
io.entgra.task.mgt.core.config.datasource.JNDILookupDefinition jndiConfig = config.getJndiLookupDefinition();
if (jndiConfig != null) {
if (log.isDebugEnabled()) {
log.debug("Initializing Device Management Repository data source using the JNDI " +
"Lookup Definition");
}
List<JNDILookupDefinition.JNDIProperty> jndiPropertyList =
jndiConfig.getJndiProperties();
if (jndiPropertyList != null) {
Hashtable<Object, Object> jndiProperties = new Hashtable<Object, Object>();
for (JNDILookupDefinition.JNDIProperty prop : jndiPropertyList) {
jndiProperties.put(prop.getName(), prop.getValue());
}
dataSource = TaskManagementDAOUtil.lookupDataSource(jndiConfig.getJndiName(), jndiProperties);
} else {
dataSource = TaskManagementDAOUtil.lookupDataSource(jndiConfig.getJndiName(), null);
}
}
return dataSource;
}
}

@ -0,0 +1,176 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.core.dao.impl;
import io.entgra.task.mgt.common.bean.DynamicTask;
import io.entgra.task.mgt.common.exception.TaskManagementDAOException;
import io.entgra.task.mgt.core.dao.DynamicTaskDAO;
import io.entgra.task.mgt.core.dao.common.TaskManagementDAOFactory;
import io.entgra.task.mgt.core.dao.util.TaskManagementDAOUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import java.sql.*;
import java.util.List;
public class DynamicTaskDAOImpl implements DynamicTaskDAO {
private static final Log log = LogFactory.getLog(DynamicTaskDAOImpl.class);
@Override
public int addTask(DynamicTask dynamicTask) throws TaskManagementDAOException {
PreparedStatement stmt = null;
ResultSet rs = null;
int taskId = -1;
try {
Connection conn = TaskManagementDAOFactory.getConnection();
String sql = "INSERT INTO DYNAMIC_TASK(CRON, NAME, IS_ENABLED, TASK_CLASS_NAME, TENANT_ID) " +
"VALUES (?, ?, ?, ?, ?)";
stmt = conn.prepareStatement(sql, new String[]{"DYNAMIC_TASK_ID"});
stmt.setString(1, dynamicTask.getCronExpression());
stmt.setString(2, dynamicTask.getName());
stmt.setBoolean(3, dynamicTask.isEnabled());
stmt.setString(4, dynamicTask.getTaskClassName());
stmt.setInt(5, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId());
stmt.executeUpdate();
rs = stmt.getGeneratedKeys();
if (rs.next()) {
taskId = rs.getInt(1);
}
return taskId;
} catch (SQLException e) {
String msg = "Error occurred while inserting task '" + dynamicTask.getName() + "'";
log.error(msg, e);
throw new TaskManagementDAOException(msg, e);
} finally {
TaskManagementDAOUtil.cleanupResources(stmt, null);
}
}
@Override
public boolean updateDynamicTask(DynamicTask dynamicTask) throws TaskManagementDAOException {
PreparedStatement stmt = null;
int rows;
try {
Connection conn = TaskManagementDAOFactory.getConnection();
String sql = "UPDATE DYNAMIC_TASK SET CRON = ?,IS_ENABLED = ? WHERE DYNAMIC_TASK_ID = ?";
stmt = conn.prepareStatement(sql);
stmt.setString(1, dynamicTask.getCronExpression());
stmt.setBoolean(2, dynamicTask.isEnabled());
stmt.setInt(3, dynamicTask.getDynamicTaskId());
rows = stmt.executeUpdate();
return (rows > 0);
} catch (SQLException e) {
String msg = "Error occurred while updating dynamic task '" + dynamicTask.getDynamicTaskId() + "'";
log.error(msg, e);
throw new TaskManagementDAOException(msg, e);
} finally {
TaskManagementDAOUtil.cleanupResources(stmt, null);
}
}
@Override
public void deleteDynamicTask(int dynamicTaskId) throws TaskManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete dynamic task with the id: " + dynamicTaskId);
}
String sql = "DELETE FROM DYNAMIC_TASK WHERE DYNAMIC_TASK_ID = ? AND TENANT_ID = ?";
try {
Connection conn = TaskManagementDAOFactory.getConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
stmt.setInt(1, dynamicTaskId);
stmt.setInt(2, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId());
stmt.executeUpdate();
}
} catch (SQLException e) {
String msg = "Error occurred while executing SQL to delete a dynamic task which has the id " +
dynamicTaskId;
log.error(msg, e);
throw new TaskManagementDAOException(msg, e);
}
}
@Override
public DynamicTask getDynamicTaskById(int dynamicTaskId) throws TaskManagementDAOException {
DynamicTask dynamicTask = null;
try {
Connection conn = TaskManagementDAOFactory.getConnection();
String sql = "SELECT * FROM DYNAMIC_TASK WHERE DYNAMIC_TASK_ID= ? AND TENANT_ID = ?";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, dynamicTaskId);
stmt.setInt(2, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId());
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
dynamicTask = TaskManagementDAOUtil.loadDynamicTask(rs);
}
}
}
} catch (SQLException e) {
String msg = "Error occurred while getting dynamic task data for task identifier '" +
dynamicTask + "'";
log.error(msg, e);
throw new TaskManagementDAOException(msg, e);
}
return dynamicTask;
}
@Override
public List<DynamicTask> getAllDynamicTasks() throws TaskManagementDAOException {
List<DynamicTask> dynamicTasks = null;
try {
Connection conn = TaskManagementDAOFactory.getConnection();
String sql = "SELECT * FROM DYNAMIC_TASK";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
try (ResultSet rs = stmt.executeQuery()) {
dynamicTasks = TaskManagementDAOUtil.loadDynamicTasks(rs);
}
}
} catch (SQLException e) {
String msg = "Error occurred while getting all dynamic task data ";
log.error(msg, e);
throw new TaskManagementDAOException(msg, e);
}
return dynamicTasks;
}
@Override
public List<DynamicTask> getActiveDynamicTasks() throws TaskManagementDAOException {
List<DynamicTask> dynamicTasks = null;
try {
Connection conn = TaskManagementDAOFactory.getConnection();
String sql = "SELECT * FROM DYNAMIC_TASK WHERE IS_ENABLED = 'true' ";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
try (ResultSet rs = stmt.executeQuery()) {
dynamicTasks = TaskManagementDAOUtil.loadDynamicTasks(rs);
}
}
} catch (SQLException e) {
String msg = "Error occurred while getting all dynamic task data ";
log.error(msg, e);
throw new TaskManagementDAOException(msg, e);
}
return dynamicTasks;
}
}

@ -0,0 +1,124 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.core.dao.impl;
import io.entgra.task.mgt.common.constant.TaskMgtConstants;
import io.entgra.task.mgt.common.exception.TaskManagementDAOException;
import io.entgra.task.mgt.core.dao.DynamicTaskPropDAO;
import io.entgra.task.mgt.core.dao.common.TaskManagementDAOFactory;
import io.entgra.task.mgt.core.dao.util.TaskManagementDAOUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
public class DynamicTaskPropDAOImpl implements DynamicTaskPropDAO {
private static final Log log = LogFactory.getLog(DynamicTaskPropDAOImpl.class);
@Override
public void addTaskProperties(int taskId, Map<String, String> properties)
throws TaskManagementDAOException {
Connection conn = null;
PreparedStatement stmt = null;
try {
conn = TaskManagementDAOFactory.getConnection();
stmt = conn.prepareStatement(
"INSERT INTO DYNAMIC_TASK_PROPERTIES(DYNAMIC_TASK_ID, PROPERTY_NAME, " +
"PROPERTY_VALUE, TENANT_ID) VALUES (?, ?, ?, ?)");
for (String propertyKey : properties.keySet()) {
stmt.setInt(1, taskId);
stmt.setString(2, propertyKey);
stmt.setString(3, properties.get(propertyKey));
stmt.setInt(4, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId());
stmt.addBatch();
}
stmt.executeBatch();
} catch (SQLException e) {
String msg = "Error occurred while adding task properties of task '" + taskId + "' to the db.";
log.error(msg, e);
throw new TaskManagementDAOException(msg, e);
} finally {
TaskManagementDAOUtil.cleanupResources(stmt, null);
}
}
public Map<String, String> getDynamicTaskProps(int dynamicTaskId) throws TaskManagementDAOException {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet resultSet = null;
Map<String, String> properties;
try {
conn = TaskManagementDAOFactory.getConnection();
stmt = conn.prepareStatement(
"SELECT * FROM DYNAMIC_TASK_PROPERTIES WHERE DYNAMIC_TASK_ID = ?");
stmt.setInt(1, dynamicTaskId);
resultSet = stmt.executeQuery();
properties = new HashMap<>();
while (resultSet.next()) {
properties.put(resultSet.getString(TaskMgtConstants.Task.PROPERTY_KEY_COLUMN_NAME)
, resultSet.getString(TaskMgtConstants.Task.PROPERTY_VALUE_COLUMN_NAME));
}
} catch (SQLException e) {
String msg = "Error occurred while fetching task properties of : '" + dynamicTaskId + "'";
log.error(msg, e);
throw new TaskManagementDAOException(msg, e);
} finally {
TaskManagementDAOUtil.cleanupResources(stmt, resultSet);
}
return properties;
}
@Override
public void updateDynamicTaskProps(int dynamicTaskId, Map<String, String> properties)
throws TaskManagementDAOException {
if (properties.isEmpty()) {
if (log.isDebugEnabled()) {
log.debug("Property map of task id :" + dynamicTaskId + " is empty.");
}
return;
}
Connection conn;
PreparedStatement stmt = null;
try {
conn = TaskManagementDAOFactory.getConnection();
stmt = conn.prepareStatement("UPDATE DYNAMIC_TASK_PROPERTIES SET PROPERTY_VALUE = ? " +
"WHERE DYNAMIC_TASK_ID = ? AND PROPERTY_NAME = ?");
for (Map.Entry<String, String> entry : properties.entrySet()) {
stmt.setString(1, entry.getValue());
stmt.setInt(2, dynamicTaskId);
stmt.setString(3, entry.getKey());
stmt.addBatch();
}
stmt.executeBatch();
} catch (SQLException e) {
throw new TaskManagementDAOException
("Error occurred while updating device properties to database.", e);
} finally {
TaskManagementDAOUtil.cleanupResources(stmt, null);
}
}
}

@ -0,0 +1,110 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.core.dao.util;
import io.entgra.task.mgt.common.bean.DynamicTask;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
public class TaskManagementDAOUtil {
private static final Log log = LogFactory.getLog(TaskManagementDAOUtil.class);
public static void cleanupResources(Connection conn, PreparedStatement stmt, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
log.warn("Error occurred while closing result set", e);
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
log.warn("Error occurred while closing prepared statement", e);
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
log.warn("Error occurred while closing database connection", e);
}
}
}
public static void cleanupResources(PreparedStatement stmt, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
log.warn("Error occurred while closing result set", e);
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
log.warn("Error occurred while closing prepared statement", e);
}
}
}
public static DataSource lookupDataSource(String dataSourceName,
final Hashtable<Object, Object> jndiProperties) {
try {
if (jndiProperties == null || jndiProperties.isEmpty()) {
return (DataSource) InitialContext.doLookup(dataSourceName);
}
final InitialContext context = new InitialContext(jndiProperties);
return (DataSource) context.lookup(dataSourceName);
} catch (Exception e) {
throw new RuntimeException("Error in looking up data source: " + e.getMessage(), e);
}
}
public static DynamicTask loadDynamicTask(ResultSet rs) throws SQLException {
DynamicTask dynamicTask = new DynamicTask();
dynamicTask.setDynamicTaskId(rs.getInt("DYNAMIC_TASK_ID"));
dynamicTask.setName(rs.getString("NAME"));
dynamicTask.setCronExpression(rs.getString("CRON"));
dynamicTask.setTaskClassName(rs.getString("TASK_CLASS_NAME"));
dynamicTask.setEnabled(rs.getBoolean("IS_ENABLED"));
dynamicTask.setTenantId(rs.getInt("TENANT_ID"));
return dynamicTask;
}
public static List<DynamicTask> loadDynamicTasks(ResultSet rs) throws SQLException {
List<DynamicTask> dynamicTasks = new ArrayList<>();
while (rs.next()) {
dynamicTasks.add(loadDynamicTask(rs));
}
return dynamicTasks;
}
}

@ -0,0 +1,62 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.core.internal;
import io.entgra.server.bootup.heartbeat.beacon.service.HeartBeatManagementService;
import io.entgra.task.mgt.common.spi.TaskManagementService;
import org.wso2.carbon.ntask.core.service.TaskService;
public class TaskManagerDataHolder {
private TaskManagementService taskManagerService;
private TaskService nTaskService;
private HeartBeatManagementService heartBeatService;
private static final TaskManagerDataHolder thisInstance = new TaskManagerDataHolder();
private TaskManagerDataHolder() {
}
public static TaskManagerDataHolder getInstance() {
return thisInstance;
}
public TaskManagementService getTaskManagementService() {
return taskManagerService;
}
public void setTaskManagementService(TaskManagementService taskManagerService) {
this.taskManagerService = taskManagerService;
}
public TaskService getnTaskService() {
return nTaskService;
}
public void setnTaskService(TaskService nTaskService) {
this.nTaskService = nTaskService;
}
public HeartBeatManagementService getHeartBeatService() {
return heartBeatService;
}
public void setHeartBeatService(HeartBeatManagementService heartBeatService) {
this.heartBeatService = heartBeatService;
}
}

@ -0,0 +1,134 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.core.internal;
import io.entgra.server.bootup.heartbeat.beacon.service.HeartBeatManagementService;
import io.entgra.task.mgt.core.config.TaskManagementConfig;
import io.entgra.task.mgt.core.config.datasource.DataSourceConfig;
import io.entgra.task.mgt.common.spi.TaskManagementService;
import io.entgra.task.mgt.core.config.TaskConfigurationManager;
import io.entgra.task.mgt.core.dao.common.TaskManagementDAOFactory;
import io.entgra.task.mgt.core.service.TaskManagementServiceImpl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.ndatasource.core.DataSourceService;
import org.wso2.carbon.ntask.core.service.TaskService;
/**
* @scr.component name="io.entgra.task.mgt.service" immediate="true"
* @scr.reference name="datasource.service"
* interface="org.wso2.carbon.ndatasource.core.DataSourceService"
* cardinality="1..1"
* policy="dynamic"
* bind="setDataSourceService"
* unbind="unsetDataSourceService"
* @scr.reference name="app.mgt.ntask.component"
* interface="org.wso2.carbon.ntask.core.service.TaskService"
* cardinality="1..1"
* policy="dynamic"
* bind="setTaskService"
* unbind="unsetTaskService"
* @scr.reference name="entgra.heart.beat.service"
* interface="io.entgra.server.bootup.heartbeat.beacon.service.HeartBeatManagementService"
* cardinality="0..1"
* policy="dynamic"
* bind="setHeartBeatService"
* unbind="unsetHeartBeatService"
*/
public class TaskManagerServiceComponent {
private static final Log log = LogFactory.getLog(TaskManagerServiceComponent.class);
protected void activate(ComponentContext ctx) {
if (log.isDebugEnabled()) {
log.debug("Activating Task Manager Service Component");
}
try {
TaskManagementConfig taskManagementConfig = TaskConfigurationManager.getInstance()
.getTaskManagementConfig();
DataSourceConfig dataSourceConfig = taskManagementConfig.getTaskMgtConfigRepository()
.getDataSourceConfig();
TaskManagementDAOFactory.init(dataSourceConfig);
BundleContext bundleContext = ctx.getBundleContext();
TaskManagementService taskManagementService = new TaskManagementServiceImpl();
taskManagementService.init();
TaskManagerDataHolder.getInstance().setTaskManagementService(taskManagementService);
bundleContext.registerService(TaskManagementService.class.getName()
, taskManagementService, null);
if (log.isDebugEnabled()) {
log.debug("Task Manager Service Component has been successfully activated");
}
} catch (Throwable e) {
log.error("Error occurred while activating Task Manager Service Component", e);
}
}
protected void deactivate(ComponentContext ctx) {
if (log.isDebugEnabled()) {
log.debug("De-activating Task Manager Service Component");
}
}
protected void setDataSourceService(DataSourceService dataSourceService) {
/* This is to avoid Task Manager Service Component getting initialized before the underlying datasources
are registered */
if (log.isDebugEnabled()) {
log.debug("Data source service set to Task Manager Service Component ");
}
}
protected void unsetDataSourceService(DataSourceService dataSourceService) {
//do nothing
}
@SuppressWarnings("unused")
public void setTaskService(TaskService taskService) {
if (log.isDebugEnabled()) {
log.debug("Setting the task service to Task Manager Service Component");
}
TaskManagerDataHolder.getInstance().setnTaskService(taskService);
}
@SuppressWarnings("unused")
protected void unsetTaskService(TaskService taskService) {
if (log.isDebugEnabled()) {
log.debug("Removing the task service from Task Manager Service Component");
}
TaskManagerDataHolder.getInstance().setnTaskService(null);
}
@SuppressWarnings("unused")
protected void setHeartBeatService(HeartBeatManagementService heartBeatService) {
if (log.isDebugEnabled()) {
log.debug("Setting heart beat service to Task Manager Service Component");
}
TaskManagerDataHolder.getInstance().setHeartBeatService(heartBeatService);
}
@SuppressWarnings("unused")
protected void unsetHeartBeatService(HeartBeatManagementService heartBeatManagementService) {
if (log.isDebugEnabled()) {
log.debug("Removing heart beat service from Task Manager Service Component");
}
TaskManagerDataHolder.getInstance().setHeartBeatService(null);
}
}

@ -0,0 +1,397 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (https://entgra.io) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.core.service;
import io.entgra.server.bootup.heartbeat.beacon.exception.HeartBeatManagementException;
import io.entgra.task.mgt.common.bean.DynamicTask;
import io.entgra.task.mgt.common.constant.TaskMgtConstants;
import io.entgra.task.mgt.common.exception.TaskManagementDAOException;
import io.entgra.task.mgt.common.exception.TaskManagementException;
import io.entgra.task.mgt.common.exception.TaskNotFoundException;
import io.entgra.task.mgt.common.exception.TransactionManagementException;
import io.entgra.task.mgt.common.spi.TaskManagementService;
import io.entgra.task.mgt.core.dao.DynamicTaskDAO;
import io.entgra.task.mgt.core.dao.DynamicTaskPropDAO;
import io.entgra.task.mgt.core.dao.common.TaskManagementDAOFactory;
import io.entgra.task.mgt.core.internal.TaskManagerDataHolder;
import io.entgra.task.mgt.core.util.TaskManagementUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.ntask.common.TaskException;
import org.wso2.carbon.ntask.core.TaskInfo;
import org.wso2.carbon.ntask.core.TaskManager;
import org.wso2.carbon.ntask.core.service.TaskService;
import java.util.List;
import java.util.Map;
public class TaskManagementServiceImpl implements TaskManagementService {
private static final Log log = LogFactory.getLog(TaskManagementServiceImpl.class);
private final DynamicTaskDAO dynamicTaskDAO;
private final DynamicTaskPropDAO dynamicTaskPropDAO;
private TaskManager taskManager;
public TaskManagementServiceImpl() {
this.dynamicTaskDAO = TaskManagementDAOFactory.getDynamicTaskDAO();
this.dynamicTaskPropDAO = TaskManagementDAOFactory.getDynamicTaskPropDAO();
}
@Override
public void init() throws TaskManagementException {
TaskService nTaskService = TaskManagerDataHolder.getInstance().getnTaskService();
if (nTaskService == null) {
String msg = "Unable to load TaskService, hence unable to schedule the task.";
log.error(msg);
throw new TaskManagementException(msg);
}
if (!nTaskService.getRegisteredTaskTypes().contains(TaskMgtConstants.Task.DYNAMIC_TASK_TYPE)) {
try {
nTaskService.registerTaskType(TaskMgtConstants.Task.DYNAMIC_TASK_TYPE);
this.taskManager = nTaskService.getTaskManager(TaskMgtConstants.Task.DYNAMIC_TASK_TYPE);
} catch (TaskException e) {
String msg = "Error occurred while registering task type ["
+ TaskMgtConstants.Task.DYNAMIC_TASK_TYPE
+ "], hence unable to schedule the task.";
log.error(msg);
throw new TaskManagementException(msg, e);
}
}
}
@Override
public void createTask(DynamicTask dynamicTask) throws TaskManagementException {
String taskId;
try {
// add into the dynamic task tables
TaskManagementDAOFactory.beginTransaction();
int dynamicTaskId = dynamicTaskDAO.addTask(dynamicTask);
Map<String, String> taskProperties = dynamicTask.getProperties();
dynamicTaskPropDAO.addTaskProperties(dynamicTaskId, taskProperties);
// add into the ntask core
taskId = TaskManagementUtil.generateTaskId(dynamicTaskId);
try {
int serverHashIdx = TaskManagerDataHolder.getInstance().getHeartBeatService()
.getServerCtxInfo().getLocalServerHashIdx();
taskProperties.put(TaskMgtConstants.Task.LOCAL_HASH_INDEX, String.valueOf(serverHashIdx));
taskProperties.put(TaskMgtConstants.Task.LOCAL_TASK_NAME, taskId);
} catch (HeartBeatManagementException e) {
String msg = "Unexpected exception when getting server hash index.";
log.error(msg, e);
throw new TaskManagementException(msg, e);
}
if (!isTaskExists(taskId)) {
TaskInfo.TriggerInfo triggerInfo = new TaskInfo.TriggerInfo();
triggerInfo.setCronExpression(dynamicTask.getCronExpression());
TaskInfo taskInfo = new TaskInfo(taskId, dynamicTask.getTaskClassName(), taskProperties, triggerInfo);
taskManager.registerTask(taskInfo);
taskManager.scheduleTask(taskId);
if (!dynamicTask.isEnabled()) {
taskManager.pauseTask(taskId);
}
} else {
String msg = "Task '" + taskId + "' is already exists in the ntask core "
+ "Hence not creating another task for the same name.";
log.error(msg);
}
TaskManagementDAOFactory.commitTransaction();
} catch (TaskManagementDAOException e) {
TaskManagementDAOFactory.rollbackTransaction();
String msg = "Failed to add dynamic task " + dynamicTask.getName();
log.error(msg, e);
throw new TaskManagementException(msg, e);
} catch (TransactionManagementException e) {
String msg = "Failed to start/open transaction to add dynamic task";
log.error(msg, e);
throw new TaskManagementException(msg, e);
} catch (TaskException e) {
TaskManagementDAOFactory.rollbackTransaction();
String msg = "Error occurred while scheduling task '" + dynamicTask.getName() + "'";
log.error(msg, e);
throw new TaskManagementException(msg, e);
} finally {
TaskManagementDAOFactory.closeConnection();
}
}
@Override
public void updateTask(int dynamicTaskId, DynamicTask dynamicTask) throws TaskManagementException
, TaskNotFoundException {
try {
//Update dynamic task table
TaskManagementDAOFactory.beginTransaction();
DynamicTask existingTask = dynamicTaskDAO.getDynamicTaskById(dynamicTaskId);
if (existingTask != null) {
existingTask.setEnabled(dynamicTask.isEnabled());
existingTask.setCronExpression(dynamicTask.getCronExpression());
dynamicTaskDAO.updateDynamicTask(existingTask);
if (!dynamicTask.getProperties().isEmpty()) {
dynamicTaskPropDAO.updateDynamicTaskProps(dynamicTaskId, dynamicTask.getProperties());
}
} else {
String msg = "Task '" + dynamicTaskId + "' is not exists in the dynamic task table.";
log.error(msg);
throw new TaskNotFoundException(msg);
}
// Update task in the ntask core
String taskId = TaskManagementUtil.generateTaskId(existingTask.getDynamicTaskId());
if (isTaskExists(taskId)) {
TaskInfo taskInfo = taskManager.getTask(taskId);
if (!dynamicTask.getProperties().isEmpty()) {
taskInfo.setProperties(dynamicTask.getProperties());
}
TaskInfo.TriggerInfo triggerInfo;
if (taskInfo.getTriggerInfo() == null) {
triggerInfo = new TaskInfo.TriggerInfo();
} else {
triggerInfo = taskInfo.getTriggerInfo();
}
triggerInfo.setCronExpression(dynamicTask.getCronExpression());
taskInfo.setTriggerInfo(triggerInfo);
taskManager.registerTask(taskInfo);
taskManager.rescheduleTask(taskId);
} else {
String msg = "Task '" + taskId + "' is not exists in the n task core "
+ "Hence cannot update the task.";
log.error(msg);
}
TaskManagementDAOFactory.commitTransaction();
} catch (TaskManagementDAOException e) {
TaskManagementDAOFactory.rollbackTransaction();
String msg = "Failed to update dynamic task " + dynamicTask.getDynamicTaskId();
log.error(msg, e);
throw new TaskManagementException(msg, e);
} catch (TransactionManagementException e) {
String msg = "Failed to start/open transaction to update dynamic task";
log.error(msg, e);
throw new TaskManagementException(msg, e);
} catch (TaskException e) {
TaskManagementDAOFactory.rollbackTransaction();
String msg = "Error occurred while updating task '" + dynamicTask.getDynamicTaskId() + "'";
log.error(msg);
throw new TaskManagementException(msg, e);
} finally {
TaskManagementDAOFactory.closeConnection();
}
}
@Override
public void toggleTask(int dynamicTaskId, boolean isEnabled) throws TaskManagementException
, TaskNotFoundException {
try {
//update dynamic task table
TaskManagementDAOFactory.beginTransaction();
DynamicTask existingTask = dynamicTaskDAO.getDynamicTaskById(dynamicTaskId);
if (existingTask != null) {
existingTask.setEnabled(isEnabled);
dynamicTaskDAO.updateDynamicTask(existingTask);
} else {
String msg = "Task '" + dynamicTaskId + "' is not exists.";
log.error(msg);
throw new TaskNotFoundException(msg);
}
// Update task in the ntask core
String taskId = TaskManagementUtil.generateTaskId(existingTask.getDynamicTaskId());
if (isTaskExists(taskId)) {
if (isEnabled) {
taskManager.resumeTask(taskId);
} else {
taskManager.pauseTask(taskId);
}
} else {
String msg = "Task '" + taskId + "' is not exists in the ntask core "
+ "Hence cannot toggle the task in the ntask.";
log.error(msg);
}
TaskManagementDAOFactory.commitTransaction();
} catch (TaskManagementDAOException e) {
TaskManagementDAOFactory.rollbackTransaction();
String msg = "Failed to toggle dynamic task " + dynamicTaskId;
log.error(msg, e);
throw new TaskManagementException(msg, e);
} catch (TransactionManagementException e) {
String msg = "Failed to start/open transaction to toggle dynamic task";
log.error(msg, e);
throw new TaskManagementException(msg, e);
} catch (TaskException e) {
String msg = "Error occurred while toggling task '" + dynamicTaskId + "' to '" + isEnabled + "'";
log.error(msg);
throw new TaskManagementException(msg, e);
} finally {
TaskManagementDAOFactory.closeConnection();
}
}
@Override
public void deleteTask(int dynamicTaskId) throws TaskManagementException, TaskNotFoundException {
// delete task from dynamic task table
try {
TaskManagementDAOFactory.beginTransaction();
DynamicTask existingTask = dynamicTaskDAO.getDynamicTaskById(dynamicTaskId);
if (existingTask != null) {
dynamicTaskDAO.deleteDynamicTask(dynamicTaskId);
} else {
String msg = "Task '" + dynamicTaskId + "' is not exists.";
log.error(msg);
throw new TaskNotFoundException(msg);
}
String taskId = TaskManagementUtil.generateTaskId(existingTask.getDynamicTaskId());
if (isTaskExists(taskId)) {
taskManager.deleteTask(taskId);
} else {
String msg = "Task '" + taskId + "' is not exists in the ntask core "
+ "Hence cannot delete from the ntask core.";
log.error(msg);
}
TaskManagementDAOFactory.commitTransaction();
} catch (TaskManagementDAOException e) {
TaskManagementDAOFactory.rollbackTransaction();
String msg = "Failed to update dynamic task " + dynamicTaskId;
log.error(msg, e);
throw new TaskManagementException(msg, e);
} catch (TransactionManagementException e) {
String msg = "Failed to start/open transaction to delete dynamic task";
log.error(msg, e);
throw new TaskManagementException(msg, e);
} catch (TaskException e) {
TaskManagementDAOFactory.rollbackTransaction();
String msg = "Error occurred while retrieving task manager to delete task '" + dynamicTaskId + "'";
log.error(msg);
throw new TaskManagementException(msg, e);
} finally {
TaskManagementDAOFactory.closeConnection();
}
}
@Override
public List<DynamicTask> getAllDynamicTasks() throws TaskManagementException {
List<DynamicTask> dynamicTasks;
try {
if (log.isDebugEnabled()) {
log.debug("Fetching the details of all dynamic tasks");
}
TaskManagementDAOFactory.beginTransaction();
dynamicTasks = dynamicTaskDAO.getAllDynamicTasks();
if (dynamicTasks != null) {
for (DynamicTask dynamicTask : dynamicTasks) {
dynamicTask.setProperties(dynamicTaskPropDAO
.getDynamicTaskProps(dynamicTask.getDynamicTaskId()));
}
}
TaskManagementDAOFactory.commitTransaction();
} catch (TaskManagementDAOException e) {
TaskManagementDAOFactory.rollbackTransaction();
String msg = "Error occurred while fetching all dynamic tasks";
log.error(msg, e);
throw new TaskManagementException(msg, e);
} catch (TransactionManagementException e) {
String msg = "Failed to start/open transaction to get all dynamic tasks";
log.error(msg, e);
throw new TaskManagementException(msg, e);
} finally {
TaskManagementDAOFactory.closeConnection();
}
return dynamicTasks;
}
@Override
public DynamicTask getDynamicTaskById(int dynamicTaskId) throws TaskManagementException {
DynamicTask dynamicTask;
try {
if (log.isDebugEnabled()) {
log.debug("Fetching the details of dynamic task '" + dynamicTaskId + "'");
}
TaskManagementDAOFactory.beginTransaction();
dynamicTask = dynamicTaskDAO.getDynamicTaskById(dynamicTaskId);
if (dynamicTask != null) {
dynamicTask.setProperties(dynamicTaskPropDAO.getDynamicTaskProps(dynamicTask.getDynamicTaskId()));
}
TaskManagementDAOFactory.commitTransaction();
} catch (TaskManagementDAOException e) {
TaskManagementDAOFactory.rollbackTransaction();
String msg = "Error occurred while fetching dynamic task '" + dynamicTaskId + "'";
log.error(msg, e);
throw new TaskManagementException(msg, e);
} catch (TransactionManagementException e) {
String msg = "Failed to start/open transaction to get dynamic task '" + dynamicTaskId + "'";
log.error(msg, e);
throw new TaskManagementException(msg, e);
} finally {
TaskManagementDAOFactory.closeConnection();
}
return dynamicTask;
}
@Override
public List<DynamicTask> getActiveDynamicTasks() throws TaskManagementException {
List<DynamicTask> dynamicTasks;
try {
if (log.isDebugEnabled()) {
log.debug("Fetching the details of all active dynamic tasks");
}
TaskManagementDAOFactory.beginTransaction();
dynamicTasks = dynamicTaskDAO.getActiveDynamicTasks();
if (dynamicTasks != null) {
for (DynamicTask dynamicTask : dynamicTasks) {
dynamicTask.setProperties(dynamicTaskPropDAO.getDynamicTaskProps(dynamicTask.getDynamicTaskId()));
}
}
TaskManagementDAOFactory.commitTransaction();
} catch (TaskManagementDAOException e) {
TaskManagementDAOFactory.rollbackTransaction();
String msg = "Error occurred while fetching all active dynamic tasks";
log.error(msg, e);
throw new TaskManagementException(msg, e);
} catch (TransactionManagementException e) {
String msg = "Failed to start/open transaction to get all active dynamic tasks";
log.error(msg, e);
throw new TaskManagementException(msg, e);
} finally {
TaskManagementDAOFactory.closeConnection();
}
return dynamicTasks;
}
// check whether task exist in the ntask core
private boolean isTaskExists(String taskId) throws TaskManagementException, TaskException {
if (StringUtils.isEmpty(taskId)) {
String msg = "Task ID must not be null or empty.";
log.error(msg);
throw new TaskManagementException(msg);
}
List<TaskInfo> tasks = taskManager.getAllTasks();
for (TaskInfo t : tasks) {
if (taskId.equals(t.getName())) {
return true;
}
}
return false;
}
}

@ -0,0 +1,84 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.core.util;
import com.google.gson.Gson;
import io.entgra.server.bootup.heartbeat.beacon.exception.HeartBeatManagementException;
import io.entgra.task.mgt.common.constant.TaskMgtConstants;
import io.entgra.task.mgt.common.exception.TaskManagementException;
import io.entgra.task.mgt.core.internal.TaskManagerDataHolder;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.util.Map;
/**
* Provides utility methods required by the task management bundle.
*/
public class TaskManagementUtil {
private static final Log log = LogFactory.getLog(TaskManagementUtil.class);
public static Document convertToDocument(File file) throws TaskManagementException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
DocumentBuilder docBuilder = factory.newDocumentBuilder();
return docBuilder.parse(file);
} catch (Exception e) {
throw new TaskManagementException(
"Error occurred while parsing file, while converting " +
"to a org.w3c.dom.Document : " + e.getMessage(), e);
}
}
public static String generateTaskId(int dynamicTaskId) throws TaskManagementException {
try {
int serverHashIdx = TaskManagerDataHolder.getInstance().getHeartBeatService()
.getServerCtxInfo().getLocalServerHashIdx();
return generateTaskId(dynamicTaskId, serverHashIdx);
} catch (HeartBeatManagementException e) {
String msg = "Failed to generate task id for a dynamic task " + dynamicTaskId;
log.error(msg, e);
throw new TaskManagementException(msg, e);
}
}
public static String generateTaskId(int dynamicTaskId, int serverHashIdx) {
return TaskMgtConstants.Task.DYNAMIC_TASK_TYPE + TaskMgtConstants.Task.NAME_SEPARATOR + dynamicTaskId
+ TaskMgtConstants.Task.NAME_SEPARATOR + serverHashIdx;
}
public static String generateTaskPropsMD5(Map<String, String> taskProperties) {
taskProperties.remove(TaskMgtConstants.Task.TENANT_ID_PROP);
taskProperties.remove(TaskMgtConstants.Task.LOCAL_HASH_INDEX);
taskProperties.remove(TaskMgtConstants.Task.LOCAL_TASK_NAME);
Gson gson = new Gson();
String json = gson.toJson(taskProperties);
return DigestUtils.md5Hex(json);
}
}

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
~
~ Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
~ Version 2.0 (the "License"); you may not use this file except
~ in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>task-mgt</artifactId>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>task-manager</artifactId>
<name>Entgra IoT - Task Manager Component</name>
<packaging>pom</packaging>
<url>http://entgra.io</url>
<modules>
<module>io.entgra.task.mgt.core</module>
<module>io.entgra.task.mgt.common</module>
</modules>
</project>

@ -0,0 +1,140 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
~
~ Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
~ Version 2.0 (the "License"); you may not use this file except
~ in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>task-watcher</artifactId>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>io.entgra.task.mgt.watcher</artifactId>
<packaging>bundle</packaging>
<name>Entgra IoT - Task Watcher </name>
<description>Entgra IoT - Task Watcher</description>
<url>http://entgra.io</url>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Bundle-Version>${carbon.device.mgt.version}</Bundle-Version>
<Bundle-Description>Task Watcher Bundle</Bundle-Description>
<Private-Package>io.entgra.task.mgt.watcher.internal</Private-Package>
<Import-Package>
io.entgra.server.bootup.heartbeat.beacon.*,
io.entgra.task.mgt.common.*,
io.entgra.task.mgt.core.*,
org.apache.commons.logging,
org.osgi.framework.*;version="${imp.package.version.osgi.framework}",
org.osgi.service.*;version="${imp.package.version.osgi.service}",
org.wso2.carbon.context,
org.wso2.carbon.core,
org.wso2.carbon.device.mgt.common.*,
org.wso2.carbon.ntask.*,
org.wso2.carbon.user.api,
org.wso2.carbon.user.core.*,
</Import-Package>
<Export-Package>
io.entgra.task.mgt.watcher.*
</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.services</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.task.mgt.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.task.mgt.common</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.common</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.server.bootup.heartbeat.beacon</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.user.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.user.api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.utils</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

@ -0,0 +1,260 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.watcher;
import io.entgra.server.bootup.heartbeat.beacon.exception.HeartBeatManagementException;
import io.entgra.task.mgt.common.bean.DynamicTask;
import io.entgra.task.mgt.common.constant.TaskMgtConstants;
import io.entgra.task.mgt.common.exception.TaskManagementException;
import io.entgra.task.mgt.core.util.TaskManagementUtil;
import io.entgra.task.mgt.watcher.internal.TaskWatcherDataHolder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.core.ServerStartupObserver;
import org.wso2.carbon.ntask.common.TaskException;
import org.wso2.carbon.ntask.core.TaskInfo;
import org.wso2.carbon.ntask.core.TaskManager;
import org.wso2.carbon.ntask.core.service.TaskService;
import org.wso2.carbon.user.api.Tenant;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.core.service.RealmService;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
public class IoTSStartupHandler implements ServerStartupObserver {
private static final Log log = LogFactory.getLog(IoTSStartupHandler.class);
@Override
public void completingServerStartup() {
}
@Override
public void completedServerStartup() {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
try {
compareTasks();
} catch (Exception e) {
log.error("Error occurred when comparing tasks.", e);
}
}
}, 200000, 300000);
}
private void compareTasks() {
if (log.isDebugEnabled()) {
log.debug("Comparing Tasks from carbon nTask manager and entgra task manager");
}
TaskService nTaskService = TaskWatcherDataHolder.getInstance().getnTaskService();
if (nTaskService == null) {
String msg = "Unable to load TaskService from the carbon nTask core";
log.error(msg);
return;
}
try {
List<DynamicTask> dynamicTasks = TaskWatcherDataHolder.getInstance().getTaskManagementService()
.getAllDynamicTasks();
scheduleMissingTasks(nTaskService, dynamicTasks);
deleteObsoleteTasks(nTaskService, dynamicTasks);
if (log.isDebugEnabled()) {
log.debug("Task Comparison Completed and all tasks in current node are updated");
}
} catch (TaskException e) {
String msg = "Error occurred while accessing carbon nTask manager.";
log.error(msg, e);
} catch (TaskManagementException e) {
String msg = "Error occurred while retrieving all active tasks from entgra task manager";
log.error(msg, e);
}
}
private static void scheduleMissingTasks(TaskService nTaskService, List<DynamicTask> dynamicTasks)
throws TaskException, TaskManagementException {
Map<Integer, List<DynamicTask>> tenantedDynamicTasks = new HashMap<>();
List<DynamicTask> dts;
for (DynamicTask dt : dynamicTasks) {
if (tenantedDynamicTasks.containsKey(dt.getTenantId())) {
dts = tenantedDynamicTasks.get(dt.getTenantId());
} else {
dts = new ArrayList<>();
}
dts.add(dt);
tenantedDynamicTasks.put(dt.getTenantId(), dts);
}
TaskManager taskManager;
for (Integer tenantId : tenantedDynamicTasks.keySet()) {
if (tenantId == -1) {
log.warn("Found " + tenantedDynamicTasks.get(tenantId).size() +
" invalid tasks without a valid tenant id.");
continue;
}
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId, true);
if (!nTaskService.getRegisteredTaskTypes().contains(TaskMgtConstants.Task.DYNAMIC_TASK_TYPE)) {
nTaskService.registerTaskType(TaskMgtConstants.Task.DYNAMIC_TASK_TYPE);
}
taskManager = nTaskService.getTaskManager(TaskMgtConstants.Task.DYNAMIC_TASK_TYPE);
List<TaskInfo> tasks = taskManager.getAllTasks();
// add or update task into nTask core
for (DynamicTask dt : tenantedDynamicTasks.get(tenantId)) {
String generatedTaskId = TaskManagementUtil.generateTaskId(dt.getDynamicTaskId());
boolean isExist = false;
for (TaskInfo taskInfo : tasks) {
if (taskInfo.getName().equals(generatedTaskId)) {
isExist = true;
TaskInfo.TriggerInfo triggerInfo = taskInfo.getTriggerInfo();
String dynamicTaskPropMD5 = TaskManagementUtil.generateTaskPropsMD5(dt.getProperties());
String existingTaskPropMD5 = TaskManagementUtil.generateTaskPropsMD5(taskInfo.getProperties());
if (!triggerInfo.getCronExpression().equals(dt.getCronExpression())
|| !dynamicTaskPropMD5.equals(existingTaskPropMD5)) {
triggerInfo.setCronExpression(dt.getCronExpression());
taskInfo.setTriggerInfo(triggerInfo);
taskInfo.setProperties(populateTaskProperties(tenantId, generatedTaskId, dt.getProperties()));
taskManager.registerTask(taskInfo);
taskManager.rescheduleTask(generatedTaskId);
if (log.isDebugEnabled()) {
log.debug("Task - '" + generatedTaskId + "' updated according to the dynamic task table");
}
}
if (dt.isEnabled()
&& taskManager.getTaskState(generatedTaskId) == TaskManager.TaskState.PAUSED) {
taskManager.resumeTask(generatedTaskId);
if (log.isDebugEnabled()) {
log.debug("Task - '" + generatedTaskId + "' enabled according to the dynamic task table");
}
} else if (!dt.isEnabled()
&& taskManager.getTaskState(generatedTaskId) != TaskManager.TaskState.PAUSED) {
taskManager.pauseTask(generatedTaskId);
if (log.isDebugEnabled()) {
log.debug("Task - '" + generatedTaskId + "' disabled according to the dynamic task table");
}
}
break;
}
}
if (!isExist) {
TaskInfo.TriggerInfo triggerInfo = new TaskInfo.TriggerInfo();
triggerInfo.setCronExpression(dt.getCronExpression());
TaskInfo taskInfo = new TaskInfo(generatedTaskId, dt.getTaskClassName(),
populateTaskProperties(tenantId, generatedTaskId, dt.getProperties()), triggerInfo);
taskManager.registerTask(taskInfo);
taskManager.scheduleTask(generatedTaskId);
if (log.isDebugEnabled()) {
log.debug("New task -'" + generatedTaskId + "' created according to the dynamic task table");
}
}
}
PrivilegedCarbonContext.endTenantFlow();
}
}
private static Map<String, String> populateTaskProperties(int tenantId, String generatedTaskId,
Map<String, String> taskProperties)
throws TaskManagementException {
try {
int serverHashIdx = TaskWatcherDataHolder.getInstance().getHeartBeatService()
.getServerCtxInfo().getLocalServerHashIdx();
taskProperties.put(TaskMgtConstants.Task.LOCAL_HASH_INDEX, String.valueOf(serverHashIdx));
taskProperties.put(TaskMgtConstants.Task.LOCAL_TASK_NAME, generatedTaskId);
taskProperties.put(TaskMgtConstants.Task.TENANT_ID_PROP, String.valueOf(tenantId));
return taskProperties;
} catch (HeartBeatManagementException e) {
String msg = "Unexpected exception when getting server hash index.";
log.error(msg, e);
throw new TaskManagementException(msg, e);
}
}
private static void deleteObsoleteTasks(TaskService nTaskService, List<DynamicTask> dynamicTasks)
throws TaskManagementException, TaskException {
List<Tenant> tenants = new ArrayList<>();
try {
RealmService realmService = TaskWatcherDataHolder.getInstance().getRealmService();
Tenant[] tenantArray = realmService.getTenantManager().getAllTenants();
if (tenantArray != null && tenantArray.length != 0) {
tenants.addAll(Arrays.asList(tenantArray));
}
Tenant superTenant = new Tenant();
superTenant.setId(-1234);
tenants.add(superTenant);
} catch (UserStoreException e) {
String msg = "Unable to load tenants";
log.error(msg, e);
return;
}
TaskManager taskManager;
Set<Integer> hashIds;
try {
hashIds = TaskWatcherDataHolder.getInstance().getHeartBeatService().getActiveServers().keySet();
} catch (HeartBeatManagementException e) {
String msg = "Unexpected exception when getting hash indexes of active servers";
log.error(msg, e);
throw new TaskManagementException(msg, e);
}
for (Tenant tenant : tenants) {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenant.getId(), true);
if (!nTaskService.getRegisteredTaskTypes().contains(TaskMgtConstants.Task.DYNAMIC_TASK_TYPE)) {
nTaskService.registerTaskType(TaskMgtConstants.Task.DYNAMIC_TASK_TYPE);
}
taskManager = nTaskService.getTaskManager(TaskMgtConstants.Task.DYNAMIC_TASK_TYPE);
List<TaskInfo> tasks = taskManager.getAllTasks();
// Remove deleted items from the nTask core
for (TaskInfo taskInfo : tasks) {
boolean isExist = false;
for (DynamicTask dt : dynamicTasks) {
for (int hid : hashIds) {
if (tenant.getId() == dt.getTenantId() &&
taskInfo.getName().equals(TaskManagementUtil.generateTaskId(dt.getDynamicTaskId(), hid))) {
isExist = true;
break;
}
}
if (isExist) {
break;
}
}
if (!isExist) {
taskManager.deleteTask(taskInfo.getName());
if (log.isDebugEnabled()) {
log.debug("Task '" + taskInfo.getName() + "' deleted according to the dynamic task table");
}
}
}
PrivilegedCarbonContext.endTenantFlow();
}
}
}

@ -0,0 +1,73 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.watcher.internal;
import io.entgra.server.bootup.heartbeat.beacon.service.HeartBeatManagementService;
import io.entgra.task.mgt.common.spi.TaskManagementService;
import org.wso2.carbon.ntask.core.service.TaskService;
import org.wso2.carbon.user.core.service.RealmService;
public class TaskWatcherDataHolder {
private TaskManagementService taskManagerService;
private TaskService nTaskService;
private HeartBeatManagementService heartBeatService;
private RealmService realmService;
private static final TaskWatcherDataHolder thisInstance = new TaskWatcherDataHolder();
private TaskWatcherDataHolder() {}
public static TaskWatcherDataHolder getInstance() {
return thisInstance;
}
public TaskManagementService getTaskManagementService() {
return taskManagerService;
}
public void setTaskManagementService(TaskManagementService taskManagerService) {
this.taskManagerService = taskManagerService;
}
public TaskService getnTaskService() {
return nTaskService;
}
public void setnTaskService(TaskService nTaskService) {
this.nTaskService = nTaskService;
}
public HeartBeatManagementService getHeartBeatService() {
return heartBeatService;
}
public void setHeartBeatService(HeartBeatManagementService heartBeatService) {
this.heartBeatService = heartBeatService;
}
public RealmService getRealmService() {
return this.realmService;
}
public void setRealmService(RealmService realmService) {
this.realmService = realmService;
}
}

@ -0,0 +1,167 @@
/*
* Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved.
*
* Entgra Pvt Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.task.mgt.watcher.internal;
import io.entgra.server.bootup.heartbeat.beacon.service.HeartBeatManagementService;
import io.entgra.task.mgt.common.spi.TaskManagementService;
import io.entgra.task.mgt.core.config.TaskConfigurationManager;
import io.entgra.task.mgt.core.config.TaskManagementConfig;
import io.entgra.task.mgt.watcher.IoTSStartupHandler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.core.ServerStartupObserver;
import org.wso2.carbon.ntask.core.service.TaskService;
import org.wso2.carbon.user.core.service.RealmService;
/**
* @scr.component
* name="io.entgra.task.mgt.watcher" immediate="true"
* @scr.reference name="app.mgt.ntask.component"
* interface="org.wso2.carbon.ntask.core.service.TaskService"
* cardinality="1..1"
* policy="dynamic"
* bind="setTaskService"
* unbind="unsetTaskService"
* @scr.reference name="io.entgra.task.mgt.service"
* interface="io.entgra.task.mgt.common.spi.TaskManagementService"
* cardinality="1..1"
* policy="dynamic"
* bind="setTaskMgtService"
* unbind="unsetTaskMgtService"
* @scr.reference name="entgra.heart.beat.service"
* interface="io.entgra.server.bootup.heartbeat.beacon.service.HeartBeatManagementService"
* cardinality="0..1"
* policy="dynamic"
* bind="setHeartBeatService"
* unbind="unsetHeartBeatService"
* @scr.reference name="user.realmservice.default"
* interface="org.wso2.carbon.user.core.service.RealmService"
* cardinality="1..1"
* policy="dynamic"
* bind="setRealmService"
* unbind="unsetRealmService"
*/
public class TaskWatcherServiceComponent {
private static final Log log = LogFactory.getLog(TaskWatcherServiceComponent.class);
protected void activate(ComponentContext ctx) {
if (log.isDebugEnabled()) {
log.debug("Activating Task Watcher Service Component");
}
try {
TaskManagementConfig taskManagementConfig = TaskConfigurationManager.getInstance().getTaskManagementConfig();
if (taskManagementConfig.isTaskWatcherEnabled()) {
BundleContext bundleContext = ctx.getBundleContext();
bundleContext.registerService(ServerStartupObserver.class.getName(), new IoTSStartupHandler(), null);
} else {
String msg = "Task watcher is not enabled in this environment hence wso2 carbon ntask will not " +
"update according to the task manager ";
log.debug(msg);
}
if (log.isDebugEnabled()) {
log.debug("Task Watcher Service Component has been successfully activated");
}
} catch (Throwable e) {
log.error("Error occurred while activating Task Watcher Service Component", e);
}
}
protected void deactivate(ComponentContext ctx) {
if (log.isDebugEnabled()) {
log.debug("De-activating Task Watcher Service Component");
}
}
@SuppressWarnings("unused")
public void setTaskService(TaskService taskService) {
if (log.isDebugEnabled()) {
log.debug("Setting the task service to Task Watcher Service Component ");
}
TaskWatcherDataHolder.getInstance().setnTaskService(taskService);
}
@SuppressWarnings("unused")
protected void unsetTaskService(TaskService taskService) {
if (log.isDebugEnabled()) {
log.debug("Removing the task service from Task Watcher Service Component ");
}
TaskWatcherDataHolder.getInstance().setnTaskService(null);
}
@SuppressWarnings("unused")
protected void setTaskMgtService(TaskManagementService taskManagementService) {
if (log.isDebugEnabled()) {
log.debug("Setting the task service to Task Watcher Service Component ");
}
TaskWatcherDataHolder.getInstance().setTaskManagementService(taskManagementService);
}
@SuppressWarnings("unused")
protected void unsetTaskMgtService(TaskManagementService taskManagementService) {
if (log.isDebugEnabled()) {
log.debug("Removing the task service from Task Watcher Service Component ");
}
TaskWatcherDataHolder.getInstance().setTaskManagementService(null);
}
@SuppressWarnings("unused")
protected void setHeartBeatService(HeartBeatManagementService heartBeatService) {
if (log.isDebugEnabled()) {
log.debug("Setting heart beat service to Task Manager Service Component");
}
TaskWatcherDataHolder.getInstance().setHeartBeatService(heartBeatService);
}
@SuppressWarnings("unused")
protected void unsetHeartBeatService(HeartBeatManagementService heartBeatManagementService) {
if (log.isDebugEnabled()) {
log.debug("Removing heart beat service from Task Manager Service Component");
}
TaskWatcherDataHolder.getInstance().setHeartBeatService(null);
}
/**
* Sets Realm Service.
*
* @param realmService An instance of RealmService
*/
@SuppressWarnings("unused")
protected void setRealmService(RealmService realmService) {
if (log.isDebugEnabled()) {
log.debug("Setting Realm Service");
}
TaskWatcherDataHolder.getInstance().setRealmService(realmService);
}
/**
* Unsets Realm Service.
*
* @param realmService An instance of RealmService
*/
@SuppressWarnings("unused")
protected void unsetRealmService(RealmService realmService) {
if (log.isDebugEnabled()) {
log.debug("Unsetting Realm Service");
}
TaskWatcherDataHolder.getInstance().setRealmService(null);
}
}

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
~
~ Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
~ Version 2.0 (the "License"); you may not use this file except
~ in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>task-mgt</artifactId>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>task-watcher</artifactId>
<name>Entgra IoT - Task Watcher Component</name>
<packaging>pom</packaging>
<url>http://entgra.io</url>
<modules>
<module>io.entgra.task.mgt.watcher</module>
</modules>
</project>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>email-sender</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>transport-mgt</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -3,7 +3,7 @@
<parent>
<artifactId>carbon-devicemgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>sms-handler</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>sms-handler</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>sms-handler</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>transport-mgt</artifactId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<artifactId>ui-request-interceptor</artifactId>
<groupId>io.entgra.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

@ -21,7 +21,7 @@
<parent>
<artifactId>carbon-devicemgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.19-SNAPSHOT</version>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save