Add dynamic task manager and task watcher (#65)

## Purpose

To Distribute dynamic task execution in multiple nodes.

## Goals

This allows distribute task execution in multiple nodes. Especially this is useful, when system has multiple nodes

## Approach

- Add task manager to handle dynamic tasks and dynamic task properties while adding   task into the wso2 ntask core.
- Add task watcher to run periodically after iot server start up and compare tasks 	 from Entgra task manager and wso2 ntask core.
- Add configuration to enable task monitoring in task watcher.

## Documentation
> N/A

## Automation tests
 - Unit tests
   > N/A
 - Integration tests
   > N/A

## Security checks
   > N/A

## Related MRs
 > N/A

## Test environment
Linux 22.04

## Learning
> N/A

Reviewed-on: community/device-mgt-core#65
Co-authored-by: Chamindu Senanayake <chamindu@entgra.io>
Co-committed-by: Chamindu Senanayake <chamindu@entgra.io>
improvement/fix-task-deletion
Chamindu Senanayake 2 years ago committed by Charitha Goonetilleke
parent 2d56b0ea9a
commit 89e72bdf86

@ -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,52 @@
/*
* 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 TaskMgtConstant {
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__";
}
}

@ -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,132 @@
<?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.*,
org.wso2.carbon.device.mgt.core.*,
org.wso2.carbon.device.mgt.common.*,
org.wso2.carbon.context,
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>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>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>
</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.TaskMgtConstant;
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 +
TaskMgtConstant.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.TaskMgtConstant;
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.util.TaskManagementDAOUtil;
import io.entgra.task.mgt.core.dao.impl.DynamicTaskDAOImpl;
import io.entgra.task.mgt.core.dao.impl.DynamicTaskPropDAOImpl;
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 TaskMgtConstant.DataBaseTypes.DB_TYPE_H2:
case TaskMgtConstant.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 TaskMgtConstant.DataBaseTypes.DB_TYPE_H2:
case TaskMgtConstant.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,125 @@
/*
* 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.TaskMgtConstant;
import io.entgra.task.mgt.common.exception.TaskManagementDAOException;
import io.entgra.task.mgt.core.dao.DynamicTaskPropDAO;
import io.entgra.task.mgt.core.dao.util.TaskManagementDAOUtil;
import io.entgra.task.mgt.core.dao.common.TaskManagementDAOFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil;
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(TaskMgtConstant.Task.PROPERTY_KEY_COLUMN_NAME)
, resultSet.getString(TaskMgtConstant.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 {
DeviceManagementDAOUtil.cleanupResources(stmt, null);
}
}
}

@ -0,0 +1,111 @@
/*
* 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 org.wso2.carbon.device.mgt.common.Device;
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 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,386 @@
/*
* 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.service;
import io.entgra.task.mgt.common.bean.DynamicTask;
import io.entgra.task.mgt.common.constant.TaskMgtConstant;
import io.entgra.task.mgt.common.exception.TaskNotFoundException;
import io.entgra.task.mgt.common.exception.TaskManagementDAOException;
import io.entgra.task.mgt.common.exception.TaskManagementException;
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(
TaskMgtConstant.Task.DYNAMIC_TASK_TYPE)) {
try {
nTaskService.registerTaskType(TaskMgtConstant.Task.DYNAMIC_TASK_TYPE);
this.taskManager = nTaskService.getTaskManager(TaskMgtConstant.Task.DYNAMIC_TASK_TYPE);
} catch (TaskException e) {
String msg = "Error occurred while registering task type ["
+ TaskMgtConstant.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);
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 cannot create another task for the same.";
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 = null;
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 = null;
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 = null;
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,80 @@
/*
* 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.TaskMgtConstant;
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.io.IOException;
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 TaskMgtConstant.Task.DYNAMIC_TASK_TYPE + TaskMgtConstant.Task.NAME_SEPARATOR + dynamicTaskId
+ TaskMgtConstant.Task.NAME_SEPARATOR + 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 generateTaskPropsMD5(Map<String, String> taskProperties) throws TaskManagementException {
if (taskProperties.containsKey(TaskMgtConstant.Task.__TENANT_ID_PROP__)) {
taskProperties.remove(TaskMgtConstant.Task.__TENANT_ID_PROP__);
}
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,109 @@
<?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>
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.ntask.*,
io.entgra.task.mgt.common.*,
io.entgra.task.mgt.core.*,
org.wso2.carbon.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.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.core</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,142 @@
/*
* 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.task.mgt.common.bean.DynamicTask;
import io.entgra.task.mgt.common.constant.TaskMgtConstant;
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.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 java.util.List;
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() {
compareTasks();
}
}, 200000, 600000);
}
private void compareTasks() {
log.info("Comparing Tasks from carbon n task manager and engtra task manager");
TaskManager taskManager = null;
TaskService nTaskService = TaskWatcherDataHolder.getInstance().getnTaskService();
if (nTaskService == null) {
String msg = "Unable to load TaskService from the carbon n task core";
log.error(msg);
}
try {
if (!nTaskService.getRegisteredTaskTypes().contains(
TaskMgtConstant.Task.DYNAMIC_TASK_TYPE)) {
nTaskService.registerTaskType(TaskMgtConstant.Task.DYNAMIC_TASK_TYPE);
}
taskManager = nTaskService.getTaskManager(TaskMgtConstant.Task.DYNAMIC_TASK_TYPE);
List<DynamicTask> dynamicTasks = TaskWatcherDataHolder.getInstance().getTaskManagementService()
.getAllDynamicTasks();
List<TaskInfo> tasks = taskManager.getAllTasks();
// add or update task into n task core
for (DynamicTask dt : dynamicTasks) {
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(dt.getProperties());
taskManager.registerTask(taskInfo);
taskManager.rescheduleTask(generatedTaskId);
log.debug("Task - '" + generatedTaskId + "' updated according to the dynamic task table");
}
if (dt.isEnabled()
&& taskManager.getTaskState(generatedTaskId) == TaskManager.TaskState.PAUSED) {
taskManager.resumeTask(generatedTaskId);
log.debug("Task - '" + generatedTaskId + "' enabled according to the dynamic task table");
} else if (!dt.isEnabled()
&& taskManager.getTaskState(generatedTaskId) != TaskManager.TaskState.PAUSED) {
taskManager.pauseTask(generatedTaskId);
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(),
dt.getProperties(), triggerInfo);
taskManager.registerTask(taskInfo);
taskManager.scheduleTask(generatedTaskId);
log.debug("New task -'" + generatedTaskId + "' created according to the dynamic task table");
}
}
// Remove deleted items from the n task core
for (TaskInfo taskInfo : tasks) {
boolean isExist = false;
for (DynamicTask dt : dynamicTasks) {
if (taskInfo.getName().equals(TaskManagementUtil.generateTaskId(dt.getDynamicTaskId()))) {
isExist = true;
}
}
if (!isExist) {
taskManager.deleteTask(taskInfo.getName());
log.debug("Task '" + taskInfo.getName() + "' deleted according to the dynamic task table");
}
}
log.info("Task Comparison Completed and all tasks in current node are updated");
} catch (
TaskException e) {
String msg = "Error occurred while accessing carbon n task manager.";
log.error(msg);
} catch (
TaskManagementException e) {
String msg = "Error occurred while retrieving all active tasks from entgra task manager";
log.error(msg);
}
}
}

@ -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.watcher.internal;
import io.entgra.task.mgt.common.spi.TaskManagementService;
import org.wso2.carbon.ntask.core.service.TaskService;
public class TaskWatcherDataHolder {
private TaskManagementService taskManagerService;
private TaskService nTaskService;
private static 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;
}
}

@ -0,0 +1,113 @@
/*
* 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.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;
/**
* @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"
*/
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);
}
}

@ -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>

@ -765,3 +765,25 @@ CREATE TABLE IF NOT EXISTS DM_EXT_PERMISSION_MAPPING (
TRACCAR_USER_ID INT DEFAULT 0 TRACCAR_USER_ID INT DEFAULT 0
); );
-- END OF DM_EXT_PERMISSION_MAPPING TABLE-- -- END OF DM_EXT_PERMISSION_MAPPING TABLE--
-- DYNAMIC TASK TABLES--
CREATE TABLE IF NOT EXISTS DYNAMIC_TASK (
DYNAMIC_TASK_ID INTEGER AUTO_INCREMENT NOT NULL,
NAME VARCHAR(300) DEFAULT NULL ,
CRON VARCHAR(8000) DEFAULT NULL,
IS_ENABLED BOOLEAN NOT NULL DEFAULT FALSE,
TASK_CLASS_NAME VARCHAR(8000) DEFAULT NULL,
TENANT_ID INTEGER DEFAULT 0,
PRIMARY KEY (DYNAMIC_TASK_ID)
);
CREATE TABLE IF NOT EXISTS DYNAMIC_TASK_PROPERTIES (
DYNAMIC_TASK_ID INTEGER NOT NULL,
PROPERTY_NAME VARCHAR(100) DEFAULT 0,
PROPERTY_VALUE VARCHAR(100) DEFAULT NULL,
TENANT_ID VARCHAR(100),
PRIMARY KEY (DYNAMIC_TASK_ID, PROPERTY_NAME, TENANT_ID),
CONSTRAINT FK_DYNAMIC_TASK_TASK_PROPERTIES FOREIGN KEY (DYNAMIC_TASK_ID) REFERENCES
DYNAMIC_TASK (DYNAMIC_TASK_ID) ON DELETE CASCADE ON UPDATE CASCADE
);
-- END OF DYNAMIC TASK TABLE--

@ -730,3 +730,27 @@ CREATE TABLE DM_GEOFENCE (
); );
-- END OF DM_GEOFENCE TABLE-- -- END OF DM_GEOFENCE TABLE--
-- DYNAMIC TASK TABLES--
IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[DYNAMIC_TASK]') AND TYPE IN (N'U'))
CREATE TABLE IF NOT EXISTS DYNAMIC_TASK (
DYNAMIC_TASK_ID INTEGER IDENTITY(1,1) NOT NULL,
NAME VARCHAR(255) DEFAULT NULL ,
CRON VARCHAR(8000) DEFAULT NULL,
IS_ENABLED BOOLEAN NOT NULL DEFAULT FALSE,
TASK_CLASS_NAME VARCHAR(8000) DEFAULT NULL,
TENANT_ID INTEGER DEFAULT 0,
PRIMARY KEY (DYNAMIC_TASK_ID)
);
IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[DYNAMIC_TASK_PROPERTIES]')
AND TYPE IN (N'U'))
CREATE TABLE IF NOT EXISTS DYNAMIC_TASK_PROPERTIES (
DYNAMIC_TASK_ID INTEGER NOT NULL,
PROPERTY_NAME VARCHAR(100) DEFAULT 0,
PROPERTY_VALUE VARCHAR(100) DEFAULT NULL,
TENANT_ID VARCHAR(100),
PRIMARY KEY (DYNAMIC_TASK_ID, PROPERTY_NAME, TENANT_ID),
CONSTRAINT FK_DYNAMIC_TASK_TASK_PROPERTIES FOREIGN KEY (DYNAMIC_TASK_ID) REFERENCES
DYNAMIC_TASK (DYNAMIC_TASK_ID) ON DELETE CASCADE ON UPDATE CASCADE
);
-- END OF DYNAMIC TASK TABLE--

@ -829,3 +829,25 @@ CREATE TABLE IF NOT EXISTS DM_EXT_PERMISSION_MAPPING (
TRACCAR_USER_ID INT DEFAULT 0 TRACCAR_USER_ID INT DEFAULT 0
); );
-- END OF DM_EXT_PERMISSION_MAPPING TABLE-- -- END OF DM_EXT_PERMISSION_MAPPING TABLE--
-- DYNAMIC TASK TABLES--
CREATE TABLE IF NOT EXISTS DYNAMIC_TASK (
DYNAMIC_TASK_ID INTEGER AUTO_INCREMENT NOT NULL,
NAME VARCHAR(300) DEFAULT NULL ,
CRON VARCHAR(8000) DEFAULT NULL,
IS_ENABLED BOOLEAN NOT NULL DEFAULT FALSE,
TASK_CLASS_NAME VARCHAR(8000) DEFAULT NULL,
TENANT_ID INTEGER DEFAULT 0,
PRIMARY KEY (DYNAMIC_TASK_ID)
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS DYNAMIC_TASK_PROPERTIES (
DYNAMIC_TASK_ID INTEGER NOT NULL,
PROPERTY_NAME VARCHAR(100) DEFAULT 0,
PROPERTY_VALUE VARCHAR(100) DEFAULT NULL,
TENANT_ID VARCHAR(100),
PRIMARY KEY (DYNAMIC_TASK_ID, PROPERTY_NAME, TENANT_ID),
CONSTRAINT FK_DYNAMIC_TASK_TASK_PROPERTIES FOREIGN KEY (DYNAMIC_TASK_ID) REFERENCES
DYNAMIC_TASK (DYNAMIC_TASK_ID) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;
-- END OF DYNAMIC TASK TABLE--

@ -1096,5 +1096,26 @@ CREATE TABLE DM_GEOFENCE (
TENANT_ID NUMBER(10) DEFAULT 0, TENANT_ID NUMBER(10) DEFAULT 0,
CONSTRAINT PK_DM_GEOFENCE PRIMARY KEY (ID) CONSTRAINT PK_DM_GEOFENCE PRIMARY KEY (ID)
); );
-- END OF DM_GEOFENCE TABLE-- -- END OF DM_GEOFENCE TABLE--
-- DYNAMIC TASK TABLES--
CREATE TABLE IF NOT EXISTS DYNAMIC_TASK (
DYNAMIC_TASK_ID NUMBER(10) NOT NULL,
NAME VARCHAR2(300) DEFAULT NULL ,
CRON VARCHAR2(8000) DEFAULT NULL,
IS_ENABLED BOOLEAN NOT NULL DEFAULT FALSE,
TASK_CLASS_NAME VARCHAR2(8000) DEFAULT NULL,
TENANT_ID INTEGER DEFAULT 0,
CONSTRAINT PK_DYNAMIC_TASK PRIMARY KEY (DYNAMIC_TASK_ID)
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS DYNAMIC_TASK_PROPERTIES (
DYNAMIC_TASK_ID INTEGER NOT NULL,
PROPERTY_NAME VARCHAR2(100) DEFAULT 0,
PROPERTY_VALUE VARCHAR2(100) DEFAULT NULL,
TENANT_ID VARCHAR2(100),
CONSTRAINT PK_DYNAMIC_TASK_PROPERTIES PRIMARY KEY (DYNAMIC_TASK_ID, PROPERTY_NAME, TENANT_ID),
CONSTRAINT FK_DYNAMIC_TASK_TASK_PROPERTIES FOREIGN KEY (DYNAMIC_TASK_ID) REFERENCES
DYNAMIC_TASK (DYNAMIC_TASK_ID) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;
-- END OF DYNAMIC TASK TABLE--

@ -750,3 +750,25 @@ CREATE TABLE IF NOT EXISTS DM_GEOFENCE (
); );
-- END OF DM_GEOFENCE TABLE-- -- END OF DM_GEOFENCE TABLE--
-- DYNAMIC TASK TABLES--
CREATE TABLE IF NOT EXISTS DYNAMIC_TASK (
DYNAMIC_TASK_ID INTEGER DEFAULT NEXTVAL ('DYNAMIC_TASK_seq') NOT NULL,
NAME VARCHAR(300) DEFAULT NULL ,
CRON VARCHAR(8000) DEFAULT NULL,
IS_ENABLED BOOLEAN NOT NULL DEFAULT FALSE,
TASK_CLASS_NAME VARCHAR(8000) DEFAULT NULL,
TENANT_ID INTEGER DEFAULT 0,
PRIMARY KEY (DYNAMIC_TASK_ID)
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS DYNAMIC_TASK_PROPERTIES (
DYNAMIC_TASK_ID INTEGER NOT NULL,
PROPERTY_NAME VARCHAR(100) DEFAULT 0,
PROPERTY_VALUE VARCHAR(100) DEFAULT NULL,
TENANT_ID VARCHAR(100),
PRIMARY KEY (DYNAMIC_TASK_ID, PROPERTY_NAME, TENANT_ID),
CONSTRAINT FK_DYNAMIC_TASK_TASK_PROPERTIES FOREIGN KEY (DYNAMIC_TASK_ID) REFERENCES
DYNAMIC_TASK (DYNAMIC_TASK_ID) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;
-- END OF DYNAMIC TASK TABLE--

@ -39,10 +39,10 @@
<{{property_name}}>{{property_value}}</{{property_name}}> <{{property_name}}>{{property_value}}</{{property_name}}>
{% endfor %} {% endfor %}
{% else %} {% else %}
<url>jdbc:mysql://localhost:3306/heart_beat</url> <url>jdbc:h2:./repository/database/HEART_BEAT_DB;AUTO_SERVER=TRUE;DB_CLOSE_ON_EXIT=FALSE</url>
<username>root</username> <username>wso2carbon</username>
<password>root</password> <password>wso2carbon</password>
<driverClassName>com.mysql.jdbc.Driver</driverClassName> <driverClassName>org.h2.Driver</driverClassName>
<maxActive>50</maxActive> <maxActive>50</maxActive>
<maxWait>60000</maxWait> <maxWait>60000</maxWait>
<testOnBorrow>true</testOnBorrow> <testOnBorrow>true</testOnBorrow>

@ -29,10 +29,10 @@
</jndiConfig> </jndiConfig>
<definition type="RDBMS"> <definition type="RDBMS">
<configuration> <configuration>
<url>jdbc:mysql://localhost:3306/heart_beat</url> <url>jdbc:h2:./repository/database/HEART_BEAT_DB;AUTO_SERVER=TRUE;DB_CLOSE_ON_EXIT=FALSE</url>
<username>root</username> <username>wso2carbon</username>
<password>root</password> <password>wso2carbon</password>
<driverClassName>com.mysql.jdbc.Driver</driverClassName> <driverClassName>org.h2.Driver</driverClassName>
<maxActive>50</maxActive> <maxActive>50</maxActive>
<maxWait>60000</maxWait> <maxWait>60000</maxWait>
<testOnBorrow>true</testOnBorrow> <testOnBorrow>true</testOnBorrow>

@ -0,0 +1,112 @@
<?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>io.entgra.task.mgt.feature</artifactId>
<packaging>pom</packaging>
<name>Entgra IoT - Task Manager Feature</name>
<url>http://wso2.org</url>
<dependencies>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.task.mgt.core</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.task.mgt.common</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>src/main/resources</outputDirectory>
<resources>
<resource>
<directory>resources</directory>
<includes>
<include>build.properties</include>
<include>p2.inf</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.wso2.maven</groupId>
<artifactId>carbon-p2-plugin</artifactId>
<version>${carbon.p2.plugin.version}</version>
<executions>
<execution>
<id>p2-feature-generation</id>
<phase>package</phase>
<goals>
<goal>p2-feature-gen</goal>
</goals>
<configuration>
<id>io.entgra.task.mgt</id>
<propertiesFile>../../../features/etc/feature.properties</propertiesFile>
<adviceFile>
<properties>
<propertyDef>org.wso2.carbon.p2.category.type:server</propertyDef>
<propertyDef>org.eclipse.equinox.p2.type.group:true</propertyDef>
</properties>
</adviceFile>
<bundles>
<bundleDef>
org.wso2.carbon.devicemgt:io.entgra.task.mgt.core:${carbon.device.mgt.version}
</bundleDef>
<bundleDef>
org.wso2.carbon.devicemgt:io.entgra.task.mgt.common:${carbon.device.mgt.version}
</bundleDef>
<bundleDef>
org.wso2.carbon.devicemgt:io.entgra.task.mgt.watcher:${carbon.device.mgt.version}
</bundleDef>
</bundles>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
~ Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
~
~ WSO2 Inc. 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.
-->
<TaskMgtConfiguration>
<ManagementRepository>
<DataSourceConfiguration>
<JndiLookupDefinition>
<Name>jdbc/DM_DS</Name>
</JndiLookupDefinition>
</DataSourceConfiguration>
</ManagementRepository>
<TaskWatcherEnable>false</TaskWatcherEnable>
</TaskMgtConfiguration>

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
~ Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
~
~ WSO2 Inc. 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.
-->
<TaskMgtConfiguration>
<ManagementRepository>
<DataSourceConfiguration>
<JndiLookupDefinition>
{% if task_mgt.datasource.name is defined %}
<Name>{{task_mgt.datasource.name}}</Name>
{% else %}
<Name>jdbc/DM_DS</Name>
{% endif %}
</JndiLookupDefinition>
</DataSourceConfiguration>
</ManagementRepository>
{% if task_watcher.conf is defined %}
<TaskWatcherEnable>{{task_watcher.conf.enable}}</TaskWatcherEnable>
{% else %}
<TaskWatcherEnable>false</TaskWatcherEnable>
{% endif %}
</TaskMgtConfiguration>

@ -0,0 +1,3 @@
instructions.configure = \
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/io.entgra.task.mgt_${feature.version}/conf/task-mgt-config.xml,target:${installFolder}/../../../repository/conf/task-mgt-config.xml,overwrite:true);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/io.entgra.task.mgt_${feature.version}/conf_templates/,target:${installFolder}/../../resources/conf/,overwrite:true);\

@ -0,0 +1,42 @@
<?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>carbon-devicemgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.20-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>task-mgt-feature</artifactId>
<packaging>pom</packaging>
<name>Entgra IoT - Task Management Feature</name>
<url>http://entgra.io</url>
<modules>
<module>io.entgra.task.mgt.feature</module>
</modules>
</project>

@ -46,6 +46,7 @@
<module>components/transport-mgt</module> <module>components/transport-mgt</module>
<module>components/analytics-mgt</module> <module>components/analytics-mgt</module>
<module>components/webapp-authenticator-framework</module> <module>components/webapp-authenticator-framework</module>
<module>components/task-mgt</module>
<module>features/device-mgt</module> <module>features/device-mgt</module>
<module>features/apimgt-extensions</module> <module>features/apimgt-extensions</module>
<module>features/application-mgt</module> <module>features/application-mgt</module>
@ -58,6 +59,8 @@
<module>features/transport-mgt</module> <module>features/transport-mgt</module>
<module>features/analytics-mgt</module> <module>features/analytics-mgt</module>
<module>features/webapp-authenticator-framework</module> <module>features/webapp-authenticator-framework</module>
<module>features/task-mgt</module>
</modules> </modules>
<dependencyManagement> <dependencyManagement>
@ -350,6 +353,29 @@
</dependency> </dependency>
<!-- Device Management dependencies --> <!-- Device Management dependencies -->
<!-- Task Management dependencies -->
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.task.mgt.common</artifactId>
<version>${carbon.device.mgt.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.task.mgt.core</artifactId>
<version>${carbon.device.mgt.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.task.mgt.watcher</artifactId>
<version>${carbon.device.mgt.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.task.mgt.feature</artifactId>
<type>zip</type>
<version>${carbon.device.mgt.version}</version>
</dependency>
<!-- Governance dependencies --> <!-- Governance dependencies -->
<dependency> <dependency>
<groupId>org.wso2.carbon</groupId> <groupId>org.wso2.carbon</groupId>
@ -2280,4 +2306,4 @@
</repository> </repository>
</distributionManagement> </distributionManagement>
</project> </project>
Loading…
Cancel
Save