forked from community/device-mgt-core
commit
7ec652a910
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*
|
||||
*/
|
||||
package org.wso2.carbon.device.mgt.jaxrs.beans;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel(value = "RemoteSessionInfo", description = "Template of the remote session")
|
||||
public class RemoteSessionInfo {
|
||||
|
||||
@ApiModelProperty(name = "Server Url", value = "Url of the remote session server.", required = true)
|
||||
private String serverUrl;
|
||||
|
||||
@ApiModelProperty(name = "isEnabled", value = "Is remote session functionality enabled", required = true)
|
||||
private Boolean isEnabled;
|
||||
|
||||
public String getServerUrl() {
|
||||
return serverUrl;
|
||||
}
|
||||
|
||||
public void setServerUrl(String serverUrl) {
|
||||
this.serverUrl = serverUrl;
|
||||
}
|
||||
|
||||
public Boolean getEnabled() {
|
||||
return isEnabled;
|
||||
}
|
||||
|
||||
public void setEnabled(Boolean enabled) {
|
||||
isEnabled = enabled;
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
|
||||
package org.wso2.carbon.device.mgt.jaxrs.service.api;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import io.swagger.annotations.ApiResponse;
|
||||
import io.swagger.annotations.ApiResponses;
|
||||
import io.swagger.annotations.Extension;
|
||||
import io.swagger.annotations.ExtensionProperty;
|
||||
import io.swagger.annotations.Info;
|
||||
import io.swagger.annotations.ResponseHeader;
|
||||
import io.swagger.annotations.SwaggerDefinition;
|
||||
import io.swagger.annotations.Tag;
|
||||
import org.wso2.carbon.apimgt.annotations.api.Scope;
|
||||
import org.wso2.carbon.apimgt.annotations.api.Scopes;
|
||||
import org.wso2.carbon.device.mgt.jaxrs.util.Constants;
|
||||
|
||||
import javax.validation.constraints.Size;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
@SwaggerDefinition(
|
||||
info = @Info(
|
||||
version = "1.0.0",
|
||||
title = "",
|
||||
extensions = {
|
||||
@Extension(properties = {
|
||||
@ExtensionProperty(name = "name", value = "remote_session_services"),
|
||||
@ExtensionProperty(name = "context", value = "/api/device-mgt/v1.0/remote-session-services"),
|
||||
})
|
||||
}
|
||||
),
|
||||
tags = {
|
||||
@Tag(name = "device_management", description = "")
|
||||
}
|
||||
)
|
||||
@Scopes(
|
||||
scopes = {
|
||||
@Scope(
|
||||
name = "Remote Session Connection",
|
||||
description = "",
|
||||
key = "perm:remote-session-service:connect",
|
||||
permissions = {"/device-mgt/devices/owning-device/remote-session"}
|
||||
)
|
||||
}
|
||||
)
|
||||
@Path("/remote-session-services")
|
||||
@Api(value = "Remote Session Service",
|
||||
description = "This carries all the resources related to the remote session service functionality.")
|
||||
public interface RemoteSessionService {
|
||||
/**
|
||||
* Retrieve Analytics for the device type
|
||||
*/
|
||||
@GET
|
||||
@Path("connection/{deviceType}/{deviceId}")
|
||||
@ApiOperation(
|
||||
consumes = "application/json",
|
||||
produces = "application/json",
|
||||
httpMethod = "GET",
|
||||
value = "Retrieve Connection Information for the device type",
|
||||
notes = "",
|
||||
response = Response.class,
|
||||
tags = "Remote Session Service Management",
|
||||
extensions = {
|
||||
@Extension(properties = {
|
||||
@ExtensionProperty(name = Constants.SCOPE, value = "perm:remote-session-service:connect")
|
||||
})
|
||||
}
|
||||
)
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(
|
||||
code = 200,
|
||||
message = "OK.",
|
||||
response = Response.class,
|
||||
responseHeaders = {
|
||||
@ResponseHeader(
|
||||
name = "Content-Type",
|
||||
description = "The content type of the body"),
|
||||
@ResponseHeader(
|
||||
name = "Last-Modified",
|
||||
description = "Date and time the resource was last modified.\n" +
|
||||
"Used by caches, or in conditional requests."),
|
||||
}),
|
||||
@ApiResponse(
|
||||
code = 400,
|
||||
message = "Bad Request. \n Invalid Device Identifiers found.",
|
||||
response = Response.class),
|
||||
@ApiResponse(
|
||||
code = 401,
|
||||
message = "Unauthorized. \n Unauthorized request."),
|
||||
@ApiResponse(
|
||||
code = 500,
|
||||
message = "Internal Server Error. \n Error on retrieving stats",
|
||||
response = Response.class)
|
||||
})
|
||||
Response getRemoteSessionDeviceConnect(
|
||||
@ApiParam(
|
||||
name = "deviceId",
|
||||
value = "The registered device Id.",
|
||||
required = true)
|
||||
@PathParam("deviceId") String deviceId,
|
||||
@ApiParam(
|
||||
name = "device-type",
|
||||
value = "The device type, such as ios, android or windows.",
|
||||
required = true)
|
||||
@PathParam("deviceType")
|
||||
@Size(max = 45)
|
||||
String deviceType);
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.jaxrs.service.impl;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager;
|
||||
import org.wso2.carbon.device.mgt.core.config.DeviceManagementConfig;
|
||||
import org.wso2.carbon.device.mgt.core.config.remote.session.RemoteSessionConfiguration;
|
||||
import org.wso2.carbon.device.mgt.jaxrs.beans.RemoteSessionInfo;
|
||||
import org.wso2.carbon.device.mgt.jaxrs.service.api.RemoteSessionService;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
/**
|
||||
* The api for
|
||||
*/
|
||||
public class RemoteSessionServiceImpl implements RemoteSessionService {
|
||||
|
||||
private static Log log = LogFactory.getLog(RemoteSessionServiceImpl.class);
|
||||
|
||||
@Path("connect/{deviceType}/{deviceId}")
|
||||
@GET
|
||||
@Consumes("application/json")
|
||||
@Produces("application/json")
|
||||
public Response getRemoteSessionDeviceConnect(@PathParam("deviceId") String deviceId,
|
||||
@PathParam("deviceType") String deviceType) {
|
||||
//First, check whether the remote session is enabled.
|
||||
RemoteSessionInfo sessionInfo = new RemoteSessionInfo();
|
||||
sessionInfo.setEnabled(false);
|
||||
DeviceManagementConfig deviceManagementConfig = DeviceConfigurationManager.getInstance()
|
||||
.getDeviceManagementConfig();
|
||||
if (deviceManagementConfig != null) {
|
||||
RemoteSessionConfiguration remoteSessionConfiguration = deviceManagementConfig.getRemoteSessionConfiguration();
|
||||
if (remoteSessionConfiguration != null) {
|
||||
boolean isEnabled = remoteSessionConfiguration.isEnabled();
|
||||
sessionInfo.setEnabled(isEnabled);
|
||||
if (isEnabled) {
|
||||
sessionInfo.setServerUrl(remoteSessionConfiguration.getRemoteSessionServerUrl());
|
||||
}
|
||||
return Response.ok().entity(sessionInfo).build();
|
||||
}
|
||||
}
|
||||
|
||||
return Response.ok().entity(sessionInfo).build();
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.archival;
|
||||
|
||||
|
||||
public class ArchivalException extends Exception {
|
||||
|
||||
private String errorMessage;
|
||||
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
public void setErrorMessage(String errorMessage) {
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public ArchivalException(String message) {
|
||||
super(message);
|
||||
setErrorMessage(message);
|
||||
}
|
||||
|
||||
public ArchivalException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
setErrorMessage(message);
|
||||
}
|
||||
|
||||
protected ArchivalException(String message, Throwable cause, boolean enableSuppression,
|
||||
boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
setErrorMessage(message);
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.archival;
|
||||
|
||||
public interface ArchivalService {
|
||||
|
||||
void archiveTransactionalRecords() throws ArchivalException;
|
||||
|
||||
void deleteArchivedRecords() throws ArchivalException;
|
||||
}
|
@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.archival;
|
||||
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.wso2.carbon.device.mgt.common.TransactionManagementException;
|
||||
import org.wso2.carbon.device.mgt.core.archival.dao.*;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class ArchivalServiceImpl implements ArchivalService {
|
||||
private static Log log = LogFactory.getLog(ArchivalServiceImpl.class);
|
||||
|
||||
private ArchivalDAO archivalDAO;
|
||||
private DataDeletionDAO dataDeletionDAO;
|
||||
|
||||
private static int ITERATION_COUNT = 10000;
|
||||
|
||||
private String[] NOT_IN_PROGRESS_OPS = new String[]{"COMPLETED", "ERROR", "REPEATED"};
|
||||
private String[] NOT_PENDING_OPS = new String[]{"COMPLETED", "ERROR", "REPEATED", "IN_PROGRESS"};
|
||||
private String[] NOT_PENDING_IN_PROGRESS_OPS = new String[]{"COMPLETED", "ERROR", "REPEATED"};
|
||||
|
||||
public ArchivalServiceImpl() {
|
||||
this.archivalDAO = ArchivalSourceDAOFactory.getDataPurgingDAO();
|
||||
this.dataDeletionDAO = ArchivalDestinationDAOFactory.getDataDeletionDAO();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void archiveTransactionalRecords() throws ArchivalException {
|
||||
try {
|
||||
ArchivalSourceDAOFactory.openConnection();
|
||||
ArchivalDestinationDAOFactory.openConnection();
|
||||
|
||||
List<Integer> allOperations = archivalDAO.getAllOperations();
|
||||
List<Integer> pendingAndIPOperations = archivalDAO.getPendingAndInProgressOperations();
|
||||
|
||||
log.info(allOperations.size() + " All Operations. " + pendingAndIPOperations.size() +
|
||||
" P&IP Operations");
|
||||
//Get the diff of operations
|
||||
Set<Integer> setA = new HashSet<>(allOperations);
|
||||
Set<Integer> setB = new HashSet<>(pendingAndIPOperations);
|
||||
setA.removeAll(setB);
|
||||
|
||||
List<Integer> candidates = new ArrayList<>();
|
||||
candidates.addAll(setA);
|
||||
|
||||
int total = candidates.size();
|
||||
int batches = calculateNumberOfBatches(total);
|
||||
int batchSize = ITERATION_COUNT;
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(total + " Operations ready for archiving. " + batches + " iterations to be done.");
|
||||
}
|
||||
|
||||
beginTransactions();
|
||||
for (int i = 1; i <= batches; i++) {
|
||||
int startIdx = batchSize * (i - 1);
|
||||
int endIdx = batchSize * i;
|
||||
if (i == batches) {
|
||||
endIdx = startIdx + (total % batchSize);
|
||||
}
|
||||
if(log.isDebugEnabled()) {
|
||||
log.debug("\n\n############ Iterating over batch " + i + "[" +
|
||||
startIdx + "," + endIdx + "] #######");
|
||||
}
|
||||
List<Integer> subList = candidates.subList(startIdx, endIdx);
|
||||
prepareTempTable(subList);
|
||||
|
||||
//Purge the largest table, DM_DEVICE_OPERATION_RESPONSE
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("## Purging operation responses");
|
||||
}
|
||||
archivalDAO.moveOperationResponses();
|
||||
|
||||
//Purge the notifications table, DM_NOTIFICATION
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("## Purging notifications");
|
||||
}
|
||||
archivalDAO.moveNotifications();
|
||||
|
||||
//Purge the command operations table, DM_COMMAND_OPERATION
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("## Purging command operations");
|
||||
}
|
||||
archivalDAO.moveCommandOperations();
|
||||
|
||||
//Purge the profile operation table, DM_PROFILE_OPERATION
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("## Purging profile operations");
|
||||
}
|
||||
archivalDAO.moveProfileOperations();
|
||||
|
||||
//Purge the enrolment mappings table, DM_ENROLMENT_OP_MAPPING
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("## Purging enrolment mappings");
|
||||
}
|
||||
archivalDAO.moveEnrolmentMappings();
|
||||
|
||||
//Finally, purge the operations table, DM_OPERATION
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("## Purging operations");
|
||||
}
|
||||
archivalDAO.moveOperations();
|
||||
}
|
||||
commitTransactions();
|
||||
} catch (ArchivalDAOException e) {
|
||||
rollbackTransactions();
|
||||
throw new ArchivalException("An error occurred while data archival", e);
|
||||
} catch (SQLException e) {
|
||||
throw new ArchivalException("An error occurred while connecting to the archival database.", e);
|
||||
} finally {
|
||||
ArchivalSourceDAOFactory.closeConnection();
|
||||
ArchivalDestinationDAOFactory.closeConnection();
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareTempTable(List<Integer> subList) throws ArchivalDAOException {
|
||||
//Clean up the DM_ARCHIVED_OPERATIONS table
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("## Truncating the temporary table");
|
||||
}
|
||||
archivalDAO.truncateOperationIDsForArchival();
|
||||
archivalDAO.copyOperationIDsForArchival(subList);
|
||||
}
|
||||
|
||||
private void beginTransactions() throws ArchivalException {
|
||||
try {
|
||||
ArchivalSourceDAOFactory.beginTransaction();
|
||||
ArchivalDestinationDAOFactory.beginTransaction();
|
||||
} catch (TransactionManagementException e) {
|
||||
log.error("An error occurred during starting transactions", e);
|
||||
throw new ArchivalException("An error occurred during starting transactions", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void commitTransactions() {
|
||||
ArchivalSourceDAOFactory.commitTransaction();
|
||||
ArchivalDestinationDAOFactory.commitTransaction();
|
||||
}
|
||||
|
||||
private void rollbackTransactions() {
|
||||
ArchivalSourceDAOFactory.rollbackTransaction();
|
||||
ArchivalDestinationDAOFactory.rollbackTransaction();
|
||||
}
|
||||
|
||||
private int calculateNumberOfBatches(int total) {
|
||||
int batches = 0;
|
||||
int batchSize = ITERATION_COUNT;
|
||||
if ((total % batchSize) > 0) {
|
||||
batches = (total / batchSize) + 1;
|
||||
} else {
|
||||
batches = total / batchSize;
|
||||
}
|
||||
return batches;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteArchivedRecords() throws ArchivalException {
|
||||
try {
|
||||
ArchivalDestinationDAOFactory.openConnection();
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("## Deleting operation responses");
|
||||
}
|
||||
dataDeletionDAO.deleteOperationResponses();
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("## Deleting notifications ");
|
||||
}
|
||||
dataDeletionDAO.deleteNotifications();
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("## Deleting command operations");
|
||||
}
|
||||
dataDeletionDAO.deleteCommandOperations();
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("## Deleting profile operations ");
|
||||
}
|
||||
dataDeletionDAO.deleteProfileOperations();
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("## Deleting enrolment mappings ");
|
||||
}
|
||||
dataDeletionDAO.deleteEnrolmentMappings();
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("## Deleting operations ");
|
||||
}
|
||||
dataDeletionDAO.deleteOperations();
|
||||
} catch (SQLException e) {
|
||||
throw new ArchivalException("An error occurred while initialising data source for archival", e);
|
||||
} catch (ArchivalDAOException e) {
|
||||
log.error("An error occurred while executing DataDeletionTask");
|
||||
} finally {
|
||||
ArchivalDestinationDAOFactory.closeConnection();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.archival.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Operations to move data from DM database to archival database
|
||||
*/
|
||||
public interface ArchivalDAO {
|
||||
|
||||
int DEFAULT_BATCH_SIZE = 1000;
|
||||
|
||||
List<Integer> getAllOperations() throws ArchivalDAOException;
|
||||
|
||||
List<Integer> getPendingAndInProgressOperations() throws ArchivalDAOException;
|
||||
|
||||
void copyOperationIDsForArchival(List<Integer> operationIds) throws ArchivalDAOException;
|
||||
|
||||
void moveOperationResponses() throws ArchivalDAOException;
|
||||
|
||||
void moveNotifications() throws ArchivalDAOException;
|
||||
|
||||
void moveCommandOperations() throws ArchivalDAOException;
|
||||
|
||||
void moveProfileOperations() throws ArchivalDAOException;
|
||||
|
||||
void moveEnrolmentMappings() throws ArchivalDAOException;
|
||||
|
||||
void moveOperations() throws ArchivalDAOException;
|
||||
|
||||
void truncateOperationIDsForArchival() throws ArchivalDAOException;
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.archival.dao;
|
||||
|
||||
|
||||
public class ArchivalDAOException extends Exception {
|
||||
|
||||
private String errorMessage;
|
||||
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
public void setErrorMessage(String errorMessage) {
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public ArchivalDAOException(String message) {
|
||||
super(message);
|
||||
setErrorMessage(message);
|
||||
}
|
||||
|
||||
public ArchivalDAOException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
setErrorMessage(message);
|
||||
}
|
||||
|
||||
protected ArchivalDAOException(String message, Throwable cause, boolean enableSuppression,
|
||||
boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
setErrorMessage(message);
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.archival.dao;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
public class ArchivalDAOUtil {
|
||||
|
||||
private static final Log log = LogFactory.getLog(ArchivalDAOUtil.class);
|
||||
|
||||
public static void cleanupResources(Statement stmt, ResultSet rs) {
|
||||
if (rs != null) {
|
||||
try {
|
||||
rs.close();
|
||||
} catch (SQLException e) {
|
||||
log.warn("Error occurred while closing the result set", e);
|
||||
}
|
||||
}
|
||||
if (stmt != null) {
|
||||
try {
|
||||
stmt.close();
|
||||
} catch (SQLException e) {
|
||||
log.warn("Error occurred while closing the statement", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void cleanupResources(Statement stmt) {
|
||||
if (stmt != null) {
|
||||
try {
|
||||
stmt.close();
|
||||
} catch (SQLException e) {
|
||||
log.warn("Error occurred while closing the statement", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.archival.dao;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.wso2.carbon.device.mgt.common.IllegalTransactionStateException;
|
||||
import org.wso2.carbon.device.mgt.common.TransactionManagementException;
|
||||
import org.wso2.carbon.device.mgt.core.archival.dao.impl.DataDeletionDAOImpl;
|
||||
import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager;
|
||||
import org.wso2.carbon.device.mgt.core.config.datasource.DataSourceConfig;
|
||||
import org.wso2.carbon.device.mgt.core.config.datasource.JNDILookupDefinition;
|
||||
import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil;
|
||||
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
|
||||
public class ArchivalDestinationDAOFactory {
|
||||
private static final Log log = LogFactory.getLog(OperationManagementDAOFactory.class);
|
||||
private static DataSource dataSource;
|
||||
private static String databaseEngine;
|
||||
private static int retentionPeriod;
|
||||
private static ThreadLocal<Connection> currentConnection = new ThreadLocal<Connection>();
|
||||
|
||||
public static DataDeletionDAO getDataDeletionDAO() {
|
||||
return new DataDeletionDAOImpl(DeviceConfigurationManager.getInstance().getDeviceManagementConfig()
|
||||
.getArchivalConfiguration().getArchivalTaskConfiguration()
|
||||
.getPurgingTaskConfiguration().getRetentionPeriod());
|
||||
}
|
||||
|
||||
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 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 beginTransaction() throws TransactionManagementException {
|
||||
try {
|
||||
Connection 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 {
|
||||
currentConnection.set(dataSource.getConnection());
|
||||
}
|
||||
|
||||
public static Connection getConnection() throws SQLException {
|
||||
if (currentConnection.get() == null) {
|
||||
throw new IllegalTransactionStateException("No connection is associated with the current transaction. " +
|
||||
"This might have ideally caused by not properly initiating the transaction via " +
|
||||
"'beginTransaction'/'openConnection' methods");
|
||||
}
|
||||
return currentConnection.get();
|
||||
}
|
||||
|
||||
public static void closeConnection() {
|
||||
Connection con = currentConnection.get();
|
||||
if (con != null) {
|
||||
try {
|
||||
con.close();
|
||||
} catch (SQLException e) {
|
||||
log.error("Error occurred while close the connection");
|
||||
}
|
||||
currentConnection.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public static void commitTransaction() {
|
||||
try {
|
||||
Connection conn = currentConnection.get();
|
||||
if (conn != null) {
|
||||
conn.commit();
|
||||
} else {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Datasource connection associated with the current thread is null, hence commit " +
|
||||
"has not been attempted");
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error("Error occurred while committing the transaction", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void rollbackTransaction() {
|
||||
try {
|
||||
Connection conn = currentConnection.get();
|
||||
if (conn != null) {
|
||||
conn.rollback();
|
||||
} else {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Datasource connection associated with the current thread is null, hence rollback " +
|
||||
"has not been attempted");
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error("Error occurred while roll-backing the transaction", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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");
|
||||
}
|
||||
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 = DeviceManagementDAOUtil.lookupDataSource(jndiConfig.getJndiName(), jndiProperties);
|
||||
} else {
|
||||
dataSource = DeviceManagementDAOUtil.lookupDataSource(jndiConfig.getJndiName(), null);
|
||||
}
|
||||
}
|
||||
return dataSource;
|
||||
}
|
||||
}
|
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.archival.dao;
|
||||
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.wso2.carbon.device.mgt.common.IllegalTransactionStateException;
|
||||
import org.wso2.carbon.device.mgt.common.TransactionManagementException;
|
||||
import org.wso2.carbon.device.mgt.core.archival.dao.impl.ArchivalDAOImpl;
|
||||
import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager;
|
||||
import org.wso2.carbon.device.mgt.core.config.archival.ArchivalTaskConfiguration;
|
||||
import org.wso2.carbon.device.mgt.core.config.datasource.DataSourceConfig;
|
||||
import org.wso2.carbon.device.mgt.core.config.datasource.JNDILookupDefinition;
|
||||
import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil;
|
||||
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
|
||||
public class ArchivalSourceDAOFactory {
|
||||
private static final Log log = LogFactory.getLog(OperationManagementDAOFactory.class);
|
||||
private static DataSource dataSource;
|
||||
private static String databaseEngine;
|
||||
private static ThreadLocal<Connection> currentConnection = new ThreadLocal<Connection>();
|
||||
|
||||
public static ArchivalDAO getDataPurgingDAO() {
|
||||
ArchivalTaskConfiguration configuration = DeviceConfigurationManager.getInstance()
|
||||
.getDeviceManagementConfig()
|
||||
.getArchivalConfiguration()
|
||||
.getArchivalTaskConfiguration();
|
||||
return new ArchivalDAOImpl(configuration.getRetentionPeriod(), configuration.getBatchSize());
|
||||
}
|
||||
|
||||
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 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 beginTransaction() throws TransactionManagementException {
|
||||
try {
|
||||
Connection 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 {
|
||||
currentConnection.set(dataSource.getConnection());
|
||||
}
|
||||
|
||||
public static Connection getConnection() throws SQLException {
|
||||
if (currentConnection.get() == null) {
|
||||
throw new IllegalTransactionStateException("No connection is associated with the current transaction. " +
|
||||
"This might have ideally caused by not properly initiating the transaction via " +
|
||||
"'beginTransaction'/'openConnection' methods");
|
||||
}
|
||||
return currentConnection.get();
|
||||
}
|
||||
|
||||
public static void closeConnection() {
|
||||
Connection con = currentConnection.get();
|
||||
if (con != null) {
|
||||
try {
|
||||
con.close();
|
||||
} catch (SQLException e) {
|
||||
log.error("Error occurred while close the connection");
|
||||
}
|
||||
currentConnection.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public static void commitTransaction() {
|
||||
try {
|
||||
Connection conn = currentConnection.get();
|
||||
if (conn != null) {
|
||||
conn.commit();
|
||||
} else {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Datasource connection associated with the current thread is null, hence commit " +
|
||||
"has not been attempted");
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error("Error occurred while committing the transaction", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void rollbackTransaction() {
|
||||
try {
|
||||
Connection conn = currentConnection.get();
|
||||
if (conn != null) {
|
||||
conn.rollback();
|
||||
} else {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Datasource connection associated with the current thread is null, hence rollback " +
|
||||
"has not been attempted");
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error("Error occurred while roll-backing the transaction", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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");
|
||||
}
|
||||
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 = DeviceManagementDAOUtil.lookupDataSource(jndiConfig.getJndiName(), jndiProperties);
|
||||
} else {
|
||||
dataSource = DeviceManagementDAOUtil.lookupDataSource(jndiConfig.getJndiName(), null);
|
||||
}
|
||||
}
|
||||
return dataSource;
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.archival.dao;
|
||||
|
||||
/**
|
||||
* Operations to permanently delete data from archived database tables
|
||||
*/
|
||||
public interface DataDeletionDAO {
|
||||
|
||||
int DEFAULT_RETENTION_PERIOD = 364;
|
||||
|
||||
void deleteOperationResponses() throws ArchivalDAOException;
|
||||
|
||||
void deleteNotifications() throws ArchivalDAOException;
|
||||
|
||||
void deleteCommandOperations() throws ArchivalDAOException;
|
||||
|
||||
void deleteProfileOperations() throws ArchivalDAOException;
|
||||
|
||||
void deleteEnrolmentMappings() throws ArchivalDAOException;
|
||||
|
||||
void deleteOperations() throws ArchivalDAOException;
|
||||
}
|
@ -0,0 +1,471 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.archival.dao.impl;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.wso2.carbon.device.mgt.core.archival.dao.*;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ArchivalDAOImpl implements ArchivalDAO {
|
||||
|
||||
private static final Log log = LogFactory.getLog(ArchivalDAOImpl.class);
|
||||
|
||||
private int retentionPeriod;
|
||||
private int batchSize = ArchivalDAO.DEFAULT_BATCH_SIZE;
|
||||
private Timestamp currentTimestamp;
|
||||
|
||||
|
||||
public ArchivalDAOImpl(int retentionPeriod) {
|
||||
this.retentionPeriod = retentionPeriod;
|
||||
}
|
||||
|
||||
public ArchivalDAOImpl(int retentionPeriod, int batchSize) {
|
||||
this.retentionPeriod = retentionPeriod;
|
||||
this.batchSize = batchSize;
|
||||
this.currentTimestamp = new Timestamp(new java.util.Date().getTime());
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Using batch size of " + this.batchSize + " with retention period " + this.retentionPeriod);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> getAllOperations() throws ArchivalDAOException {
|
||||
List<Integer> operationIds = new ArrayList<>();
|
||||
Statement stmt = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
Connection conn = ArchivalSourceDAOFactory.getConnection();
|
||||
String sql = "SELECT DISTINCT OPERATION_ID FROM DM_ENROLMENT_OP_MAPPING " +
|
||||
"WHERE CREATED_TIMESTAMP BETWEEN DATE_SUB(NOW(), INTERVAL " +
|
||||
this.retentionPeriod + " DAY) AND NOW()";
|
||||
stmt = this.createMemoryEfficientStatement(conn);
|
||||
rs = stmt.executeQuery(sql);
|
||||
while (rs.next()) {
|
||||
operationIds.add(rs.getInt("OPERATION_ID"));
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new ArchivalDAOException("An error occurred while getting a list operation Ids to archive", e);
|
||||
} finally {
|
||||
ArchivalDAOUtil.cleanupResources(stmt, rs);
|
||||
}
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(operationIds.size() + " operations found for the archival");
|
||||
}
|
||||
return operationIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> getPendingAndInProgressOperations() throws ArchivalDAOException {
|
||||
List<Integer> operationIds = new ArrayList<>();
|
||||
Statement stmt = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
Connection conn = ArchivalSourceDAOFactory.getConnection();
|
||||
String sql = "SELECT DISTINCT OPERATION_ID " +
|
||||
" FROM DM_ENROLMENT_OP_MAPPING WHERE STATUS IN('PENDING', 'IN_PROGRESS') " +
|
||||
" AND CREATED_TIMESTAMP BETWEEN DATE_SUB(NOW(), INTERVAL " + this.retentionPeriod +" DAY) AND NOW()";
|
||||
stmt = this.createMemoryEfficientStatement(conn);
|
||||
rs = stmt.executeQuery(sql);
|
||||
while (rs.next()) {
|
||||
operationIds.add(rs.getInt("OPERATION_ID"));
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new ArchivalDAOException("An error occurred while getting a list operation Ids to archive", e);
|
||||
} finally {
|
||||
ArchivalDAOUtil.cleanupResources(stmt, rs);
|
||||
}
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(operationIds.size() + " PENDING and IN_PROFRESS operations found for the archival");
|
||||
}
|
||||
return operationIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyOperationIDsForArchival(List<Integer> operationIds) throws ArchivalDAOException {
|
||||
PreparedStatement stmt = null;
|
||||
try {
|
||||
Connection conn = ArchivalSourceDAOFactory.getConnection();
|
||||
String sql = "INSERT INTO DM_ARCHIVED_OPERATIONS(ID,CREATED_TIMESTAMP) VALUES (?,NOW())";
|
||||
stmt = conn.prepareStatement(sql);
|
||||
|
||||
int count = 0;
|
||||
for (int i = 0; i < operationIds.size(); i++) {
|
||||
stmt.setInt(1, operationIds.get(i));
|
||||
stmt.addBatch();
|
||||
|
||||
if (++count % this.batchSize == 0) {
|
||||
stmt.executeBatch();
|
||||
}
|
||||
}
|
||||
stmt.executeBatch();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(count + " Records copied to the temporary table.");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new ArchivalDAOException("Error while copying operation Ids for archival", e);
|
||||
} finally {
|
||||
ArchivalDAOUtil.cleanupResources(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveOperationResponses() throws ArchivalDAOException {
|
||||
Statement stmt = null;
|
||||
PreparedStatement stmt2 = null;
|
||||
Statement stmt3 = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
Connection conn = ArchivalSourceDAOFactory.getConnection();
|
||||
String sql = "SELECT * FROM DM_DEVICE_OPERATION_RESPONSE WHERE OPERATION_ID IN " +
|
||||
"(SELECT ID FROM DM_ARCHIVED_OPERATIONS)";
|
||||
stmt = this.createMemoryEfficientStatement(conn);
|
||||
rs = stmt.executeQuery(sql);
|
||||
|
||||
Connection conn2 = ArchivalDestinationDAOFactory.getConnection();
|
||||
sql = "INSERT INTO DM_DEVICE_OPERATION_RESPONSE_ARCH VALUES(?, ?, ?, ?, ?,?,?)";
|
||||
stmt2 = conn2.prepareStatement(sql);
|
||||
|
||||
int count = 0;
|
||||
while (rs.next()) {
|
||||
stmt2.setInt(1, rs.getInt("ID"));
|
||||
stmt2.setInt(2, rs.getInt("ENROLMENT_ID"));
|
||||
stmt2.setInt(3, rs.getInt("OPERATION_ID"));
|
||||
stmt2.setInt(4, rs.getInt("EN_OP_MAP_ID"));
|
||||
stmt2.setBytes(5, rs.getBytes("OPERATION_RESPONSE"));
|
||||
stmt2.setTimestamp(6, rs.getTimestamp("RECEIVED_TIMESTAMP"));
|
||||
stmt2.setTimestamp(7, this.currentTimestamp);
|
||||
stmt2.addBatch();
|
||||
|
||||
if (++count % batchSize == 0) {
|
||||
stmt2.executeBatch();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Executing batch " + count);
|
||||
}
|
||||
}
|
||||
}
|
||||
stmt2.executeBatch();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(count + " [OPERATION_RESPONSES] Records copied to the archival table. Starting deletion");
|
||||
}
|
||||
//try the deletion now
|
||||
sql = "DELETE FROM DM_DEVICE_OPERATION_RESPONSE WHERE OPERATION_ID IN (" +
|
||||
" SELECT ID FROM DM_ARCHIVED_OPERATIONS)";
|
||||
stmt3 = conn.createStatement();
|
||||
int affected = stmt3.executeUpdate(sql);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(affected + " Rows deleted");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new ArchivalDAOException("Error occurred while moving operations ", e);
|
||||
} finally {
|
||||
ArchivalDAOUtil.cleanupResources(stmt, rs);
|
||||
ArchivalDAOUtil.cleanupResources(stmt2);
|
||||
ArchivalDAOUtil.cleanupResources(stmt3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveNotifications() throws ArchivalDAOException {
|
||||
Statement stmt = null;
|
||||
PreparedStatement stmt2 = null;
|
||||
Statement stmt3 = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
Connection conn = ArchivalSourceDAOFactory.getConnection();
|
||||
String sql = "SELECT * FROM DM_NOTIFICATION WHERE OPERATION_ID IN (SELECT ID FROM DM_ARCHIVED_OPERATIONS)";
|
||||
stmt = this.createMemoryEfficientStatement(conn);
|
||||
rs = stmt.executeQuery(sql);
|
||||
|
||||
// ArchivalDestinationDAOFactory.beginTransaction();
|
||||
Connection conn2 = ArchivalDestinationDAOFactory.getConnection();
|
||||
|
||||
sql = "INSERT INTO DM_NOTIFICATION_ARCH VALUES(?, ?, ?, ?, ?, ?, ?)";
|
||||
stmt2 = conn2.prepareStatement(sql);
|
||||
|
||||
int count = 0;
|
||||
while (rs.next()) {
|
||||
stmt2.setInt(1, rs.getInt("NOTIFICATION_ID"));
|
||||
stmt2.setInt(2, rs.getInt("DEVICE_ID"));
|
||||
stmt2.setInt(3, rs.getInt("OPERATION_ID"));
|
||||
stmt2.setInt(4, rs.getInt("TENANT_ID"));
|
||||
stmt2.setString(5, rs.getString("STATUS"));
|
||||
stmt2.setString(6, rs.getString("DESCRIPTION"));
|
||||
stmt2.setTimestamp(7, this.currentTimestamp);
|
||||
stmt2.addBatch();
|
||||
|
||||
if (++count % batchSize == 0) {
|
||||
stmt2.executeBatch();
|
||||
}
|
||||
}
|
||||
stmt2.executeBatch();
|
||||
// ArchivalDestinationDAOFactory.commitTransaction();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(count + " [NOTIFICATIONS] Records copied to the archival table. Starting deletion");
|
||||
}
|
||||
sql = "DELETE FROM DM_NOTIFICATION" +
|
||||
" WHERE OPERATION_ID IN (SELECT ID FROM DM_ARCHIVED_OPERATIONS)";
|
||||
stmt3 = conn.createStatement();
|
||||
int affected = stmt3.executeUpdate(sql);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(affected + " Rows deleted");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new ArchivalDAOException("Error occurred while moving notifications ", e);
|
||||
} finally {
|
||||
ArchivalDAOUtil.cleanupResources(stmt, rs);
|
||||
ArchivalDAOUtil.cleanupResources(stmt2);
|
||||
ArchivalDAOUtil.cleanupResources(stmt3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveCommandOperations() throws ArchivalDAOException {
|
||||
Statement stmt = null;
|
||||
PreparedStatement stmt2 = null;
|
||||
Statement stmt3 = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
Connection conn = ArchivalSourceDAOFactory.getConnection();
|
||||
String sql = "SELECT * FROM DM_COMMAND_OPERATION WHERE OPERATION_ID IN " +
|
||||
"(SELECT ID FROM DM_ARCHIVED_OPERATIONS)";
|
||||
stmt = this.createMemoryEfficientStatement(conn);
|
||||
rs = stmt.executeQuery(sql);
|
||||
|
||||
Connection conn2 = ArchivalDestinationDAOFactory.getConnection();
|
||||
|
||||
sql = "INSERT INTO DM_COMMAND_OPERATION_ARCH VALUES(?,?,?)";
|
||||
stmt2 = conn2.prepareStatement(sql);
|
||||
|
||||
int count = 0;
|
||||
while (rs.next()) {
|
||||
stmt2.setInt(1, rs.getInt("OPERATION_ID"));
|
||||
stmt2.setInt(2, rs.getInt("ENABLED"));
|
||||
stmt2.setTimestamp(3, this.currentTimestamp);
|
||||
stmt2.addBatch();
|
||||
|
||||
if (++count % batchSize == 0) {
|
||||
stmt2.executeBatch();
|
||||
}
|
||||
}
|
||||
stmt2.executeBatch();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(count + " [COMMAND_OPERATION] Records copied to the archival table. Starting deletion");
|
||||
}
|
||||
sql = "DELETE FROM DM_COMMAND_OPERATION" +
|
||||
" WHERE OPERATION_ID IN (SELECT ID FROM DM_ARCHIVED_OPERATIONS)";
|
||||
stmt3 = conn.createStatement();
|
||||
int affected = stmt3.executeUpdate(sql);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(affected + " Rows deleted");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new ArchivalDAOException("Error occurred while moving command operations", e);
|
||||
} finally {
|
||||
ArchivalDAOUtil.cleanupResources(stmt, rs);
|
||||
ArchivalDAOUtil.cleanupResources(stmt2);
|
||||
ArchivalDAOUtil.cleanupResources(stmt3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveProfileOperations() throws ArchivalDAOException {
|
||||
Statement stmt = null;
|
||||
PreparedStatement stmt2 = null;
|
||||
Statement stmt3 = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
Connection conn = ArchivalSourceDAOFactory.getConnection();
|
||||
String sql = "SELECT * FROM DM_PROFILE_OPERATION WHERE OPERATION_ID IN " +
|
||||
"(SELECT ID FROM DM_ARCHIVED_OPERATIONS)";
|
||||
stmt = this.createMemoryEfficientStatement(conn);
|
||||
rs = stmt.executeQuery(sql);
|
||||
|
||||
Connection conn2 = ArchivalDestinationDAOFactory.getConnection();
|
||||
|
||||
sql = "INSERT INTO DM_PROFILE_OPERATION_ARCH VALUES(?, ?, ?, ?)";
|
||||
stmt2 = conn2.prepareStatement(sql);
|
||||
|
||||
int count = 0;
|
||||
while (rs.next()) {
|
||||
stmt2.setInt(1, rs.getInt("OPERATION_ID"));
|
||||
stmt2.setInt(2, rs.getInt("ENABLED"));
|
||||
stmt2.setBytes(3, rs.getBytes("OPERATION_DETAILS"));
|
||||
stmt2.setTimestamp(4,this.currentTimestamp );
|
||||
stmt2.addBatch();
|
||||
|
||||
if (++count % batchSize == 0) {
|
||||
stmt2.executeBatch();
|
||||
}
|
||||
}
|
||||
stmt2.executeBatch();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(count + " [PROFILE_OPERATION] Records copied to the archival table. Starting deletion");
|
||||
}
|
||||
sql = "DELETE FROM DM_PROFILE_OPERATION" +
|
||||
" WHERE OPERATION_ID IN (SELECT ID FROM DM_ARCHIVED_OPERATIONS)";
|
||||
stmt3 = conn.createStatement();
|
||||
int affected = stmt3.executeUpdate(sql);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(affected + " Rows deleted");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new ArchivalDAOException("Error occurred while moving profile operations", e);
|
||||
} finally {
|
||||
ArchivalDAOUtil.cleanupResources(stmt, rs);
|
||||
ArchivalDAOUtil.cleanupResources(stmt2);
|
||||
ArchivalDAOUtil.cleanupResources(stmt3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveEnrolmentMappings() throws ArchivalDAOException {
|
||||
Statement stmt = null;
|
||||
PreparedStatement stmt2 = null;
|
||||
Statement stmt3 = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
Connection conn = ArchivalSourceDAOFactory.getConnection();
|
||||
String sql = "SELECT * FROM DM_ENROLMENT_OP_MAPPING WHERE OPERATION_ID IN " +
|
||||
"(SELECT ID FROM DM_ARCHIVED_OPERATIONS)";
|
||||
stmt = this.createMemoryEfficientStatement(conn);
|
||||
rs = stmt.executeQuery(sql);
|
||||
|
||||
Connection conn2 = ArchivalDestinationDAOFactory.getConnection();
|
||||
|
||||
sql = "INSERT INTO DM_ENROLMENT_OP_MAPPING_ARCH VALUES(?, ?, ?, ?, ?, ?, ?,?)";
|
||||
stmt2 = conn2.prepareStatement(sql);
|
||||
|
||||
int count = 0;
|
||||
while (rs.next()) {
|
||||
stmt2.setInt(1, rs.getInt("ID"));
|
||||
stmt2.setInt(2, rs.getInt("ENROLMENT_ID"));
|
||||
stmt2.setInt(3, rs.getInt("OPERATION_ID"));
|
||||
stmt2.setString(4, rs.getString("STATUS"));
|
||||
stmt2.setString(5, rs.getString("PUSH_NOTIFICATION_STATUS"));
|
||||
stmt2.setInt(6, rs.getInt("CREATED_TIMESTAMP"));
|
||||
stmt2.setInt(7, rs.getInt("UPDATED_TIMESTAMP"));
|
||||
stmt2.setTimestamp(8, this.currentTimestamp);
|
||||
stmt2.addBatch();
|
||||
|
||||
if (++count % batchSize == 0) {
|
||||
stmt2.executeBatch();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Executing batch " + count);
|
||||
}
|
||||
}
|
||||
}
|
||||
stmt2.executeBatch();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(count + " [ENROLMENT_OP_MAPPING] Records copied to the archival table. Starting deletion");
|
||||
}
|
||||
sql = "DELETE FROM DM_ENROLMENT_OP_MAPPING WHERE OPERATION_ID IN (" +
|
||||
"SELECT ID FROM DM_ARCHIVED_OPERATIONS)";
|
||||
stmt3 = conn.createStatement();
|
||||
int affected = stmt3.executeUpdate(sql);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(affected + " Rows deleted");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new ArchivalDAOException("Error occurred while moving enrolment mappings", e);
|
||||
} finally {
|
||||
ArchivalDAOUtil.cleanupResources(stmt, rs);
|
||||
ArchivalDAOUtil.cleanupResources(stmt2);
|
||||
ArchivalDAOUtil.cleanupResources(stmt3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveOperations() throws ArchivalDAOException {
|
||||
Statement stmt = null;
|
||||
PreparedStatement stmt2 = null;
|
||||
Statement stmt3 = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
Connection conn = ArchivalSourceDAOFactory.getConnection();
|
||||
String sql = "SELECT * FROM DM_OPERATION WHERE ID IN (SELECT ID FROM DM_ARCHIVED_OPERATIONS)";
|
||||
stmt = this.createMemoryEfficientStatement(conn);
|
||||
rs = stmt.executeQuery(sql);
|
||||
|
||||
Connection conn2 = ArchivalDestinationDAOFactory.getConnection();
|
||||
sql = "INSERT INTO DM_OPERATION_ARCH VALUES(?, ?, ?, ?, ?, ?)";
|
||||
stmt2 = conn2.prepareStatement(sql);
|
||||
|
||||
int count = 0;
|
||||
while (rs.next()) {
|
||||
stmt2.setInt(1, rs.getInt("ID"));
|
||||
stmt2.setString(2, rs.getString("TYPE"));
|
||||
stmt2.setTimestamp(3, rs.getTimestamp("CREATED_TIMESTAMP"));
|
||||
stmt2.setTimestamp(4, rs.getTimestamp("RECEIVED_TIMESTAMP"));
|
||||
stmt2.setString(5, rs.getString("OPERATION_CODE"));
|
||||
stmt2.setTimestamp(6, this.currentTimestamp);
|
||||
stmt2.addBatch();
|
||||
|
||||
if (++count % batchSize == 0) {
|
||||
stmt2.executeBatch();
|
||||
}
|
||||
}
|
||||
stmt2.executeBatch();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(count + " [OPERATIONS] Records copied to the archival table. Starting deletion");
|
||||
}
|
||||
sql = "DELETE FROM DM_OPERATION WHERE ID IN (" +
|
||||
"SELECT ID FROM DM_ARCHIVED_OPERATIONS)";
|
||||
stmt3 = conn.createStatement();
|
||||
int affected = stmt3.executeUpdate(sql);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(affected + " Rows deleted");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new ArchivalDAOException("Error occurred while moving operations", e);
|
||||
} finally {
|
||||
ArchivalDAOUtil.cleanupResources(stmt, rs);
|
||||
ArchivalDAOUtil.cleanupResources(stmt2);
|
||||
ArchivalDAOUtil.cleanupResources(stmt3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void truncateOperationIDsForArchival() throws ArchivalDAOException {
|
||||
PreparedStatement stmt = null;
|
||||
try {
|
||||
Connection conn = ArchivalSourceDAOFactory.getConnection();
|
||||
conn.setAutoCommit(false);
|
||||
String sql = "TRUNCATE DM_ARCHIVED_OPERATIONS";
|
||||
stmt = conn.prepareStatement(sql);
|
||||
stmt.addBatch();
|
||||
stmt.executeBatch();
|
||||
conn.commit();
|
||||
} catch (SQLException e) {
|
||||
throw new ArchivalDAOException("Error occurred while truncating operation Ids", e);
|
||||
} finally {
|
||||
ArchivalDAOUtil.cleanupResources(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
private Statement createMemoryEfficientStatement(Connection conn) throws ArchivalDAOException, SQLException {
|
||||
Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
|
||||
stmt.setFetchSize(Integer.MIN_VALUE);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.archival.dao.impl;
|
||||
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.wso2.carbon.device.mgt.core.archival.dao.ArchivalDAOException;
|
||||
import org.wso2.carbon.device.mgt.core.archival.dao.ArchivalDAOUtil;
|
||||
import org.wso2.carbon.device.mgt.core.archival.dao.ArchivalDestinationDAOFactory;
|
||||
import org.wso2.carbon.device.mgt.core.archival.dao.DataDeletionDAO;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class DataDeletionDAOImpl implements DataDeletionDAO {
|
||||
private static Log log = LogFactory.getLog(DataDeletionDAOImpl.class);
|
||||
|
||||
private int retentionPeriod = DataDeletionDAO.DEFAULT_RETENTION_PERIOD;
|
||||
|
||||
public DataDeletionDAOImpl(int retentionPeriod) {
|
||||
this.retentionPeriod = retentionPeriod;
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Using retention period as " + retentionPeriod);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteOperationResponses() throws ArchivalDAOException {
|
||||
PreparedStatement stmt = null;
|
||||
try {
|
||||
Connection conn = ArchivalDestinationDAOFactory.getConnection();
|
||||
conn.setAutoCommit(false);
|
||||
String sql = "DELETE FROM DM_DEVICE_OPERATION_RESPONSE_ARCH " +
|
||||
"WHERE ARCHIVED_AT < DATE_SUB(NOW(), INTERVAL ? DAY)";
|
||||
stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(1, this.retentionPeriod);
|
||||
stmt.addBatch();
|
||||
stmt.executeBatch();
|
||||
conn.commit();
|
||||
} catch (SQLException e) {
|
||||
throw new ArchivalDAOException("Error occurred while deleting operation responses", e);
|
||||
} finally {
|
||||
ArchivalDAOUtil.cleanupResources(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteNotifications() throws ArchivalDAOException {
|
||||
PreparedStatement stmt = null;
|
||||
try {
|
||||
Connection conn = ArchivalDestinationDAOFactory.getConnection();
|
||||
conn.setAutoCommit(false);
|
||||
String sql = "DELETE FROM DM_NOTIFICATION_ARCH" +
|
||||
" WHERE ARCHIVED_AT < DATE_SUB(NOW(), INTERVAL ? DAY)";
|
||||
stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(1, this.retentionPeriod);
|
||||
stmt.addBatch();
|
||||
stmt.executeBatch();
|
||||
conn.commit();
|
||||
} catch (SQLException e) {
|
||||
throw new ArchivalDAOException("Error occurred while deleting notifications", e);
|
||||
} finally {
|
||||
ArchivalDAOUtil.cleanupResources(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteCommandOperations() throws ArchivalDAOException {
|
||||
PreparedStatement stmt = null;
|
||||
try {
|
||||
Connection conn = ArchivalDestinationDAOFactory.getConnection();
|
||||
conn.setAutoCommit(false);
|
||||
String sql = "DELETE FROM DM_COMMAND_OPERATION_ARCH" +
|
||||
" WHERE ARCHIVED_AT < DATE_SUB(NOW(), INTERVAL ? DAY)";
|
||||
stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(1, this.retentionPeriod);
|
||||
stmt.addBatch();
|
||||
stmt.executeBatch();
|
||||
conn.commit();
|
||||
} catch (SQLException e) {
|
||||
throw new ArchivalDAOException("Error occurred while deleting command operations", e);
|
||||
} finally {
|
||||
ArchivalDAOUtil.cleanupResources(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteProfileOperations() throws ArchivalDAOException {
|
||||
PreparedStatement stmt = null;
|
||||
try {
|
||||
Connection conn = ArchivalDestinationDAOFactory.getConnection();
|
||||
conn.setAutoCommit(false);
|
||||
String sql = "DELETE FROM DM_PROFILE_OPERATION_ARCH" +
|
||||
" WHERE ARCHIVED_AT < DATE_SUB(NOW(), INTERVAL ? DAY)";
|
||||
stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(1, this.retentionPeriod);
|
||||
stmt.addBatch();
|
||||
stmt.executeBatch();
|
||||
conn.commit();
|
||||
} catch (SQLException e) {
|
||||
throw new ArchivalDAOException("Error occurred while deleting profile operations", e);
|
||||
} finally {
|
||||
ArchivalDAOUtil.cleanupResources(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteEnrolmentMappings() throws ArchivalDAOException {
|
||||
PreparedStatement stmt = null;
|
||||
try {
|
||||
Connection conn = ArchivalDestinationDAOFactory.getConnection();
|
||||
conn.setAutoCommit(false);
|
||||
String sql = "DELETE FROM DM_ENROLMENT_OP_MAPPING_ARCH WHERE ARCHIVED_AT < DATE_SUB(NOW(), INTERVAL ? DAY)";
|
||||
stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(1, this.retentionPeriod);
|
||||
stmt.addBatch();
|
||||
stmt.executeBatch();
|
||||
conn.commit();
|
||||
} catch (SQLException e) {
|
||||
throw new ArchivalDAOException("Error occurred while deleting enrolment mappings", e);
|
||||
} finally {
|
||||
ArchivalDAOUtil.cleanupResources(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteOperations() throws ArchivalDAOException {
|
||||
PreparedStatement stmt = null;
|
||||
try {
|
||||
Connection conn = ArchivalDestinationDAOFactory.getConnection();
|
||||
conn.setAutoCommit(false);
|
||||
String sql = "DELETE FROM DM_OPERATION_ARCH WHERE ARCHIVED_AT < DATE_SUB(NOW(), INTERVAL ? DAY)";
|
||||
stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(1, this.retentionPeriod);
|
||||
stmt.addBatch();
|
||||
stmt.executeBatch();
|
||||
conn.commit();
|
||||
} catch (SQLException e) {
|
||||
throw new ArchivalDAOException("Error occurred while deleting operations", e);
|
||||
} finally {
|
||||
ArchivalDAOUtil.cleanupResources(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.config.archival;
|
||||
|
||||
import org.wso2.carbon.device.mgt.core.config.datasource.DataSourceConfig;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* This class represents the information related to data archival configurations.
|
||||
*/
|
||||
@XmlRootElement(name = "ArchivalConfiguration")
|
||||
public class ArchivalConfiguration {
|
||||
|
||||
private DataSourceConfig dataSourceConfig;
|
||||
private ArchivalTaskConfiguration archivalTaskConfiguration;
|
||||
|
||||
@XmlElement(name = "DataSourceConfiguration", required = true)
|
||||
public DataSourceConfig getDataSourceConfig() {
|
||||
return dataSourceConfig;
|
||||
}
|
||||
|
||||
public void setDataSourceConfig(DataSourceConfig dataSourceConfig) {
|
||||
this.dataSourceConfig = dataSourceConfig;
|
||||
}
|
||||
|
||||
@XmlElement(name = "ArchivalTask", required = true)
|
||||
public ArchivalTaskConfiguration getArchivalTaskConfiguration() {
|
||||
return archivalTaskConfiguration;
|
||||
}
|
||||
|
||||
public void setArchivalTaskConfiguration(ArchivalTaskConfiguration archivalTaskConfiguration) {
|
||||
this.archivalTaskConfiguration = archivalTaskConfiguration;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.config.archival;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
@XmlRootElement(name = "ArchivalTask")
|
||||
public class ArchivalTaskConfiguration {
|
||||
private boolean enabled;
|
||||
private String cronExpression;
|
||||
private String taskClazz;
|
||||
private int retentionPeriod;
|
||||
private int batchSize;
|
||||
private PurgingTaskConfiguration purgingTaskConfiguration;
|
||||
|
||||
@XmlElement(name = "Enabled", required = true)
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
@XmlElement(name = "CronExpression", required = true)
|
||||
public String getCronExpression() {
|
||||
return cronExpression;
|
||||
}
|
||||
|
||||
public void setCronExpression(String cronExpression) {
|
||||
this.cronExpression = cronExpression;
|
||||
}
|
||||
|
||||
@XmlElement(name = "TaskClass", required = true)
|
||||
public String getTaskClazz() {
|
||||
return taskClazz;
|
||||
}
|
||||
|
||||
public void setTaskClazz(String taskClazz) {
|
||||
this.taskClazz = taskClazz;
|
||||
}
|
||||
|
||||
@XmlElement(name = "RetentionPeriod", required = true)
|
||||
public int getRetentionPeriod() {
|
||||
return retentionPeriod;
|
||||
}
|
||||
|
||||
public void setRetentionPeriod(int retentionPeriod) {
|
||||
this.retentionPeriod = retentionPeriod;
|
||||
}
|
||||
|
||||
@XmlElement(name = "PurgingTask", required = true)
|
||||
public PurgingTaskConfiguration getPurgingTaskConfiguration() {
|
||||
return purgingTaskConfiguration;
|
||||
}
|
||||
|
||||
public void setPurgingTaskConfiguration(PurgingTaskConfiguration purgingTaskConfiguration) {
|
||||
this.purgingTaskConfiguration = purgingTaskConfiguration;
|
||||
}
|
||||
|
||||
@XmlElement(name ="ExecutionBatchSize", required = true)
|
||||
public int getBatchSize() {
|
||||
return batchSize;
|
||||
}
|
||||
|
||||
public void setBatchSize(int batchSize) {
|
||||
this.batchSize = batchSize;
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.config.archival;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
@XmlRootElement(name = "PurgingTask")
|
||||
public class PurgingTaskConfiguration {
|
||||
private boolean enabled;
|
||||
private String cronExpression;
|
||||
private String taskClazz;
|
||||
private int retentionPeriod;
|
||||
|
||||
@XmlElement(name = "Enabled", required = true)
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
@XmlElement(name = "CronExpression", required = true)
|
||||
public String getCronExpression() {
|
||||
return cronExpression;
|
||||
}
|
||||
|
||||
public void setCronExpression(String cronExpression) {
|
||||
this.cronExpression = cronExpression;
|
||||
}
|
||||
|
||||
@XmlElement(name = "TaskClass", required = true)
|
||||
public String getTaskClazz() {
|
||||
return taskClazz;
|
||||
}
|
||||
|
||||
public void setTaskClazz(String taskClazz) {
|
||||
this.taskClazz = taskClazz;
|
||||
}
|
||||
|
||||
@XmlElement(name = "RetentionPeriod", required = true)
|
||||
public int getRetentionPeriod() {
|
||||
return retentionPeriod;
|
||||
}
|
||||
|
||||
public void setRetentionPeriod(int retentionPeriod) {
|
||||
this.retentionPeriod = retentionPeriod;
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
package org.wso2.carbon.device.mgt.core.config.keymanager;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* Configurations related to key management.
|
||||
*/
|
||||
@XmlRootElement(name = "KeyManagerConfiguration")
|
||||
public class KeyManagerConfigurations {
|
||||
private String serverUrl;
|
||||
private String adminUsername;
|
||||
private String adminPassword;
|
||||
|
||||
@XmlElement(name = "AdminUsername", required = true)
|
||||
public String getAdminUsername() {
|
||||
return adminUsername;
|
||||
}
|
||||
|
||||
public void setAdminUsername(String adminUsername) {
|
||||
this.adminUsername = adminUsername;
|
||||
}
|
||||
|
||||
@XmlElement(name = "AdminPassword", required = true)
|
||||
public String getAdminPassword() {
|
||||
return adminPassword;
|
||||
}
|
||||
|
||||
public void setAdminPassword(String adminPassword) {
|
||||
this.adminPassword = adminPassword;
|
||||
}
|
||||
|
||||
@XmlElement(name = "ServerUrl", required = true)
|
||||
public String getServerUrl() {
|
||||
return serverUrl;
|
||||
}
|
||||
|
||||
public void setServerUrl(String serverUrl) {
|
||||
this.serverUrl = serverUrl;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.config.remote.session;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* This class represents the information related to Remote Session configuration.
|
||||
*/
|
||||
@XmlRootElement(name = "RemoteSessionConfiguration")
|
||||
public class RemoteSessionConfiguration {
|
||||
|
||||
private String remoteSessionServerUrl;
|
||||
private boolean enabled;
|
||||
private int maxHTTPConnectionPerHost;
|
||||
private int maxTotalHTTPConnections;
|
||||
private int maxMessagesPerSecond;
|
||||
private int sessionIdleTimeOut;
|
||||
private int maxMessageBufferSize;
|
||||
|
||||
public void setRemoteSessionServerUrl(String remoteSessionServerUrl) {
|
||||
this.remoteSessionServerUrl = remoteSessionServerUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remote session server url
|
||||
* @return
|
||||
*/
|
||||
@XmlElement(name = "RemoteSessionServerUrl", required = true)
|
||||
public String getRemoteSessionServerUrl() {
|
||||
return remoteSessionServerUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remote session enabled
|
||||
* @return
|
||||
*/
|
||||
@XmlElement(name = "Enabled", required = true)
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximum connections per host for external http invocations
|
||||
* @return
|
||||
*/
|
||||
@XmlElement(name = "MaximumHTTPConnectionPerHost", required = true, defaultValue = "2")
|
||||
public int getMaxHTTPConnectionPerHost() {
|
||||
return maxHTTPConnectionPerHost;
|
||||
}
|
||||
|
||||
public void setMaxHTTPConnectionPerHost(int maxHTTPConnectionPerHost) {
|
||||
this.maxHTTPConnectionPerHost = maxHTTPConnectionPerHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximum total connections for external http invocation
|
||||
*/
|
||||
@XmlElement(name = "MaximumTotalHTTPConnections", required = true, defaultValue = "100")
|
||||
public int getMaxTotalHTTPConnections() {
|
||||
return maxTotalHTTPConnections;
|
||||
}
|
||||
|
||||
public void setMaxTotalHTTPConnections(int maxTotalHTTPConnections) {
|
||||
this.maxTotalHTTPConnections = maxTotalHTTPConnections;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is for protect device from message spamming. Throttling limit in term of messages for device
|
||||
* @return
|
||||
*/
|
||||
@XmlElement(name = "MaximumMessagesPerSecond", required = true, defaultValue = "10")
|
||||
public int getMaxMessagesPerSession() {
|
||||
return maxMessagesPerSecond;
|
||||
}
|
||||
|
||||
public void setMaxMessagesPerSession(int maxMessagesPerSession) {
|
||||
this.maxMessagesPerSecond = maxMessagesPerSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximum idle timeout in minutes
|
||||
* @return
|
||||
*/
|
||||
@XmlElement(name = "SessionIdleTimeOut", required = true, defaultValue = "5")
|
||||
public int getSessionIdleTimeOut() {
|
||||
return sessionIdleTimeOut;
|
||||
}
|
||||
|
||||
public void setSessionIdleTimeOut(int sessionIdleTimeOut) {
|
||||
this.sessionIdleTimeOut = sessionIdleTimeOut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximum session buffer size in kilo bytes
|
||||
* @return
|
||||
*/
|
||||
@XmlElement(name = "MaximumMessageBufferSize", required = true, defaultValue = "640")
|
||||
public int getMaxMessageBufferSize() {
|
||||
return maxMessageBufferSize;
|
||||
}
|
||||
|
||||
public void setMaxMessageBufferSize(int MaxMessageBufferSize) {
|
||||
this.maxMessageBufferSize = MaxMessageBufferSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,54 @@
|
||||
package org.wso2.carbon.device.mgt.core.geo;
|
||||
|
||||
import org.wso2.carbon.device.mgt.core.geo.geoHash.GeoCoordinate;
|
||||
|
||||
public class GeoCluster {
|
||||
private GeoCoordinate coordinates;
|
||||
private GeoCoordinate southWestBound;
|
||||
private GeoCoordinate northEastBound;
|
||||
private long count;
|
||||
private String geohashPrefix;
|
||||
private String deviceIdentification;
|
||||
private String deviceType;
|
||||
|
||||
|
||||
|
||||
public GeoCluster(GeoCoordinate coordinates, GeoCoordinate southWestBound, GeoCoordinate northEastBound, long count,
|
||||
String geohashPrefix, String deviceIdentification, String deviceType){
|
||||
this.coordinates=coordinates;
|
||||
this.southWestBound=southWestBound;
|
||||
this.northEastBound=northEastBound;
|
||||
this.count=count;
|
||||
this.geohashPrefix=geohashPrefix;
|
||||
this.deviceIdentification=deviceIdentification;
|
||||
this.deviceType=deviceType;
|
||||
|
||||
}
|
||||
|
||||
public String getGeohashPrefix() {
|
||||
return geohashPrefix;
|
||||
}
|
||||
|
||||
public long getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public GeoCoordinate getCoordinates() {
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
public GeoCoordinate getSouthWestBound() {
|
||||
return southWestBound;
|
||||
}
|
||||
|
||||
public GeoCoordinate getNorthEastBound() {
|
||||
return northEastBound;
|
||||
}
|
||||
|
||||
public String getDeviceIdentification() {
|
||||
return deviceIdentification;
|
||||
}
|
||||
|
||||
public String getDeviceType() { return deviceType;
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package org.wso2.carbon.device.mgt.core.geo.geoHash;
|
||||
|
||||
|
||||
|
||||
public class GeoCoordinate {
|
||||
private double latitude;
|
||||
private double longitude;
|
||||
|
||||
public GeoCoordinate(double latitude, double longitude){
|
||||
this.latitude=latitude;
|
||||
this.longitude=longitude;
|
||||
}
|
||||
|
||||
public double getLatitude() {
|
||||
return latitude;
|
||||
}
|
||||
|
||||
public double getLongitude() {
|
||||
return longitude;
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package org.wso2.carbon.device.mgt.core.geo.geoHash;
|
||||
|
||||
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class GeoHashGenerator {
|
||||
private static final String BASE_32 = "0123456789bcdefghjkmnpqrstuvwxyz";
|
||||
private static final int GEOHASH_LENGTH = 16;
|
||||
|
||||
private GeoHashGenerator(){};
|
||||
|
||||
private static int divideRangeByValue(double value, double[] range) {
|
||||
double mid = middle(range);
|
||||
if (value >= mid) {
|
||||
range[0] = mid;
|
||||
return 1;
|
||||
} else {
|
||||
range[1] = mid;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static void divideRangeByBit(int bit, double[] range) {
|
||||
double mid = middle(range);
|
||||
if (bit > 0) {
|
||||
range[0] = mid;
|
||||
} else {
|
||||
range[1] = mid;
|
||||
}
|
||||
}
|
||||
|
||||
private static double middle(double[] range) {
|
||||
return (range[0] + range[1]) / 2;
|
||||
}
|
||||
|
||||
public static String encodeGeohash(double latitude, double longitude) {
|
||||
int geohashLength=GEOHASH_LENGTH;
|
||||
double[] latRange = new double[]{-90.0, 90.0};
|
||||
double[] lonRange = new double[]{-180.0, 180.0};
|
||||
boolean isEven = true;
|
||||
int bit = 0;
|
||||
int base32CharIndex = 0;
|
||||
StringBuilder geohash = new StringBuilder();
|
||||
|
||||
while (geohash.length() < geohashLength) {
|
||||
if (isEven) {
|
||||
base32CharIndex = (base32CharIndex << 1) | divideRangeByValue(longitude, lonRange);
|
||||
} else {
|
||||
base32CharIndex = (base32CharIndex << 1) | divideRangeByValue(latitude, latRange);
|
||||
}
|
||||
|
||||
isEven = !isEven;
|
||||
|
||||
if (bit < 4) {
|
||||
bit++;
|
||||
} else {
|
||||
geohash.append(BASE_32.charAt(base32CharIndex));
|
||||
bit = 0;
|
||||
base32CharIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return geohash.toString();
|
||||
}
|
||||
|
||||
public static String encodeGeohash(DeviceLocation deviceLocation) {
|
||||
return encodeGeohash(deviceLocation.getLatitude(), deviceLocation.getLongitude());
|
||||
}
|
||||
|
||||
public static GeoCoordinate decodeGeohash(String geohash) {
|
||||
double[] latRange = new double[]{-90.0, 90.0};
|
||||
double[] lonRange = new double[]{-180.0, 180.0};
|
||||
boolean isEvenBit = true;
|
||||
|
||||
for (int i = 0; i < geohash.length(); i++) {
|
||||
int base32CharIndex = BASE_32.indexOf(geohash.charAt(i));
|
||||
for (int j = 4; j >= 0; j--) {
|
||||
if (isEvenBit) {
|
||||
divideRangeByBit((base32CharIndex >> j) & 1, lonRange);
|
||||
} else {
|
||||
divideRangeByBit((base32CharIndex >> j) & 1, latRange);
|
||||
}
|
||||
isEvenBit = !isEvenBit;
|
||||
}
|
||||
}
|
||||
GeoCoordinate coordinates = new GeoCoordinate(middle(latRange),middle(lonRange));
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package org.wso2.carbon.device.mgt.core.geo.geoHash.geoHashStrategy;
|
||||
|
||||
import org.wso2.carbon.device.mgt.core.geo.geoHash.GeoCoordinate;
|
||||
|
||||
/**
|
||||
* This interface is to decide a length for the geohash prefix
|
||||
* which will be used to group the clusters based on geohash
|
||||
*/
|
||||
public interface GeoHashLengthStrategy {
|
||||
int getGeohashLength(GeoCoordinate southWest, GeoCoordinate northEast, int zoom);
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package org.wso2.carbon.device.mgt.core.geo.geoHash.geoHashStrategy;
|
||||
|
||||
import org.wso2.carbon.device.mgt.core.geo.geoHash.GeoCoordinate;
|
||||
|
||||
/**A class that will decide the geoHashLength based on the zoom level and
|
||||
* the boundaries of the map**/
|
||||
|
||||
public class ZoomGeoHashLengthStrategy implements GeoHashLengthStrategy{
|
||||
|
||||
private int minGeohashLength = 1;
|
||||
private int maxGeohashLength = 16;
|
||||
private int minZoom = 1;
|
||||
private int maxZoom = 17;
|
||||
|
||||
@Override
|
||||
public int getGeohashLength(GeoCoordinate southWest, GeoCoordinate northEast, int zoom) {
|
||||
double a = minGeohashLength / Math.exp(minZoom / (maxZoom - minZoom) * Math.log(maxGeohashLength / minGeohashLength));
|
||||
double b = Math.log(maxGeohashLength / minGeohashLength) / (maxZoom - minZoom);
|
||||
return (int) Math.max(minGeohashLength, Math.min(a * Math.exp(b * zoom), maxGeohashLength));
|
||||
}
|
||||
|
||||
public void setMinGeohashLength(int minGeohashLength) {
|
||||
this.minGeohashLength = minGeohashLength;
|
||||
}
|
||||
|
||||
public void setMaxGeohashLength(int maxGeohashLength) {
|
||||
this.maxGeohashLength = maxGeohashLength;
|
||||
}
|
||||
|
||||
public void setMinZoom(int minZoom) {
|
||||
this.minZoom = minZoom;
|
||||
}
|
||||
|
||||
public void setMaxZoom(int maxZoom) {
|
||||
this.maxZoom = maxZoom;
|
||||
}
|
||||
|
||||
public int getMinGeohashLength() {
|
||||
return minGeohashLength;
|
||||
}
|
||||
|
||||
public int getMaxGeohashLength() {
|
||||
return maxGeohashLength;
|
||||
}
|
||||
|
||||
public int getMinZoom() {
|
||||
return minZoom;
|
||||
}
|
||||
|
||||
public int getMaxZoom() {
|
||||
return maxZoom;
|
||||
}
|
||||
}
|
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.internal;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.osgi.service.component.ComponentContext;
|
||||
import org.wso2.carbon.device.mgt.core.archival.dao.ArchivalDestinationDAOFactory;
|
||||
import org.wso2.carbon.device.mgt.core.archival.dao.ArchivalSourceDAOFactory;
|
||||
import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager;
|
||||
import org.wso2.carbon.device.mgt.core.config.DeviceManagementConfig;
|
||||
import org.wso2.carbon.device.mgt.core.config.datasource.DataSourceConfig;
|
||||
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
|
||||
import org.wso2.carbon.device.mgt.core.task.ArchivalTaskManager;
|
||||
import org.wso2.carbon.device.mgt.core.task.impl.ArchivalTaskManagerImpl;
|
||||
import org.wso2.carbon.ntask.core.service.TaskService;
|
||||
|
||||
/**
|
||||
* @scr.component name="org.wso2.carbon.activity.data.archival" immediate="true"
|
||||
* @scr.reference name="device.ntask.component"
|
||||
* interface="org.wso2.carbon.ntask.core.service.TaskService"
|
||||
* cardinality="1..1"
|
||||
* policy="dynamic"
|
||||
* bind="setTaskService"
|
||||
* unbind="unsetTaskService"
|
||||
* @scr.reference name="org.wso2.carbon.device.manager"
|
||||
* interface="org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService"
|
||||
* cardinality="1..1"
|
||||
* policy="dynamic"
|
||||
* bind="setDeviceManagementService"
|
||||
* unbind="unsetDeviceManagementService"
|
||||
*/
|
||||
public class ActivityDataPurgingServiceComponent {
|
||||
private static Log log = LogFactory.getLog(ActivityDataPurgingServiceComponent.class);
|
||||
|
||||
protected void activate(ComponentContext componentContext) {
|
||||
try {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Initializing activity data archival task manager bundle.");
|
||||
}
|
||||
|
||||
/* Initialising data archival configurations */
|
||||
DeviceManagementConfig config =
|
||||
DeviceConfigurationManager.getInstance().getDeviceManagementConfig();
|
||||
|
||||
boolean archivalTaskEnabled = false;
|
||||
boolean purgingTaskEnabled = false;
|
||||
|
||||
if (config.getArchivalConfiguration() != null
|
||||
&& config.getArchivalConfiguration().getArchivalTaskConfiguration() != null){
|
||||
archivalTaskEnabled = config.getArchivalConfiguration().getArchivalTaskConfiguration().isEnabled();
|
||||
purgingTaskEnabled = config.getArchivalConfiguration().getArchivalTaskConfiguration()
|
||||
.getPurgingTaskConfiguration() != null
|
||||
&& config.getArchivalConfiguration()
|
||||
.getArchivalTaskConfiguration().getPurgingTaskConfiguration().isEnabled();
|
||||
}
|
||||
|
||||
if (archivalTaskEnabled || purgingTaskEnabled) {
|
||||
DataSourceConfig dsConfig = config.getDeviceManagementConfigRepository().getDataSourceConfig();
|
||||
ArchivalSourceDAOFactory.init(dsConfig);
|
||||
DataSourceConfig purgingDSConfig = config.getArchivalConfiguration().getDataSourceConfig();
|
||||
ArchivalDestinationDAOFactory.init(purgingDSConfig);
|
||||
}
|
||||
|
||||
ArchivalTaskManager archivalTaskManager = new ArchivalTaskManagerImpl();
|
||||
|
||||
// This will start the data archival task
|
||||
if (archivalTaskEnabled) {
|
||||
archivalTaskManager.scheduleArchivalTask();
|
||||
log.info("Data archival task has been scheduled.");
|
||||
} else {
|
||||
log.warn("Data archival task has been disabled. It is recommended to enable archival task to " +
|
||||
"prune the transactional databases tables time to time if you are using MySQL.");
|
||||
}
|
||||
|
||||
// This will start the data deletion task.
|
||||
if (purgingTaskEnabled) {
|
||||
archivalTaskManager.scheduleDeletionTask();
|
||||
log.info("Data purging task has been scheduled for archived data.");
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
log.error("Error occurred while initializing activity data archival task manager service.", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setTaskService(TaskService taskService) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Setting the task service.");
|
||||
}
|
||||
DeviceManagementDataHolder.getInstance().setTaskService(taskService);
|
||||
}
|
||||
|
||||
protected void unsetTaskService(TaskService taskService) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Removing the task service.");
|
||||
}
|
||||
DeviceManagementDataHolder.getInstance().setTaskService(null);
|
||||
}
|
||||
|
||||
protected void setDeviceManagementService(DeviceManagementProviderService deviceManagementService){
|
||||
|
||||
}
|
||||
|
||||
protected void unsetDeviceManagementService(DeviceManagementProviderService deviceManagementService){
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
protected void deactivate(ComponentContext componentContext) {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.task;
|
||||
|
||||
public class ArchivalTaskException extends Exception {
|
||||
private String errorMessage;
|
||||
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
public void setErrorMessage(String errorMessage) {
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public ArchivalTaskException(String message) {
|
||||
super(message);
|
||||
setErrorMessage(message);
|
||||
}
|
||||
|
||||
public ArchivalTaskException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
setErrorMessage(message);
|
||||
}
|
||||
|
||||
public ArchivalTaskException(String message, Throwable cause, boolean enableSuppression,
|
||||
boolean writableStackTrace, String errorMessage) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
setErrorMessage(message);
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.task;
|
||||
|
||||
public interface ArchivalTaskManager {
|
||||
|
||||
void scheduleArchivalTask() throws ArchivalTaskException;
|
||||
|
||||
void scheduleDeletionTask() throws ArchivalTaskException;
|
||||
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.task.impl;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.wso2.carbon.device.mgt.core.archival.ArchivalException;
|
||||
import org.wso2.carbon.device.mgt.core.archival.ArchivalService;
|
||||
import org.wso2.carbon.device.mgt.core.archival.ArchivalServiceImpl;
|
||||
import org.wso2.carbon.ntask.core.Task;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
public class ArchivalTask implements Task {
|
||||
private static Log log = LogFactory.getLog(ArchivalTask.class);
|
||||
|
||||
private ArchivalService archivalService;
|
||||
|
||||
@Override
|
||||
public void setProperties(Map<String, String> map) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
this.archivalService = new ArchivalServiceImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
log.info("Executing ArchivalTask at " + new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(new Date()));
|
||||
long startTime = System.currentTimeMillis();
|
||||
try {
|
||||
archivalService.archiveTransactionalRecords();
|
||||
} catch (ArchivalException e) {
|
||||
log.error("An error occurred while running ArchivalTask", e);
|
||||
}
|
||||
long endTime = System.currentTimeMillis();
|
||||
long difference = endTime - startTime;
|
||||
log.info("ArchivalTask completed. Total execution time: " + getDurationBreakdown(difference));
|
||||
}
|
||||
|
||||
private String getDurationBreakdown(long millis) {
|
||||
if (millis < 0) {
|
||||
throw new IllegalArgumentException("Duration must be greater than zero!");
|
||||
}
|
||||
long days = TimeUnit.MILLISECONDS.toDays(millis);
|
||||
millis -= TimeUnit.DAYS.toMillis(days);
|
||||
long hours = TimeUnit.MILLISECONDS.toHours(millis);
|
||||
millis -= TimeUnit.HOURS.toMillis(hours);
|
||||
long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
|
||||
millis -= TimeUnit.MINUTES.toMillis(minutes);
|
||||
long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
|
||||
|
||||
StringBuilder sb = new StringBuilder(64);
|
||||
sb.append(days);
|
||||
sb.append(" Days ");
|
||||
sb.append(hours);
|
||||
sb.append(" Hours ");
|
||||
sb.append(minutes);
|
||||
sb.append(" Minutes ");
|
||||
sb.append(seconds);
|
||||
sb.append(" Seconds");
|
||||
|
||||
return (sb.toString());
|
||||
}
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.task.impl;
|
||||
|
||||
|
||||
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.config.DeviceConfigurationManager;
|
||||
import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder;
|
||||
import org.wso2.carbon.device.mgt.core.task.ArchivalTaskException;
|
||||
import org.wso2.carbon.device.mgt.core.task.ArchivalTaskManager;
|
||||
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.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ArchivalTaskManagerImpl implements ArchivalTaskManager {
|
||||
private static final String TASK_TYPE_ARCHIVAL = "DATA_ARCHIVAL";
|
||||
private static final String TASK_TYPE_DELETION = "DATA_DELETION";
|
||||
|
||||
private static final String TASK_NAME_ARCHIVAL = "DATA_ARCHIVAL_TASK";
|
||||
private static final String TASK_NAME_DELETION = "DATA_DELETION_TASK";
|
||||
|
||||
private static final String TENANT_ID = "TENANT_ID";
|
||||
|
||||
private static Log log = LogFactory.getLog(ArchivalTaskManagerImpl.class);
|
||||
|
||||
public void scheduleArchivalTask() throws ArchivalTaskException {
|
||||
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
|
||||
|
||||
try {
|
||||
TaskService taskService = DeviceManagementDataHolder.getInstance().getTaskService();
|
||||
taskService.registerTaskType(TASK_TYPE_ARCHIVAL);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Data archival task is started for the tenant id " + tenantId);
|
||||
}
|
||||
String taskClazz = DeviceConfigurationManager.getInstance().getDeviceManagementConfig()
|
||||
.getArchivalConfiguration().getArchivalTaskConfiguration().getTaskClazz();
|
||||
String cronExpression = DeviceConfigurationManager.getInstance().getDeviceManagementConfig()
|
||||
.getArchivalConfiguration().getArchivalTaskConfiguration().getCronExpression();
|
||||
|
||||
TaskManager taskManager = taskService.getTaskManager(TASK_TYPE_ARCHIVAL);
|
||||
|
||||
TaskInfo.TriggerInfo triggerInfo = new TaskInfo.TriggerInfo();
|
||||
triggerInfo.setCronExpression(cronExpression);
|
||||
triggerInfo.setRepeatCount(-1);
|
||||
triggerInfo.setDisallowConcurrentExecution(true);
|
||||
|
||||
Map<String, String> properties = new HashMap<>();
|
||||
properties.put(TENANT_ID, String.valueOf(tenantId));
|
||||
|
||||
if (!taskManager.isTaskScheduled(TASK_NAME_ARCHIVAL)) {
|
||||
TaskInfo taskInfo = new TaskInfo(TASK_NAME_ARCHIVAL, taskClazz, properties, triggerInfo);
|
||||
taskManager.registerTask(taskInfo);
|
||||
taskManager.rescheduleTask(taskInfo.getName());
|
||||
} else {
|
||||
throw new ArchivalTaskException("Data archival task is already started for this tenant " +
|
||||
tenantId);
|
||||
}
|
||||
|
||||
} catch (TaskException e) {
|
||||
throw new ArchivalTaskException("Error occurred while creating the task for tenant " + tenantId, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void scheduleDeletionTask() throws ArchivalTaskException {
|
||||
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
|
||||
try {
|
||||
TaskService taskService = DeviceManagementDataHolder.getInstance().getTaskService();
|
||||
taskService.registerTaskType(TASK_TYPE_DELETION);
|
||||
|
||||
String taskClazz = DeviceConfigurationManager.getInstance().getDeviceManagementConfig()
|
||||
.getArchivalConfiguration().getArchivalTaskConfiguration()
|
||||
.getPurgingTaskConfiguration().getTaskClazz();
|
||||
String cronExpression = DeviceConfigurationManager.getInstance().getDeviceManagementConfig()
|
||||
.getArchivalConfiguration().getArchivalTaskConfiguration()
|
||||
.getPurgingTaskConfiguration().getCronExpression();
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Data deletion task is started for the tenant id " + tenantId);
|
||||
}
|
||||
TaskManager taskManager = taskService.getTaskManager(TASK_TYPE_DELETION);
|
||||
|
||||
TaskInfo.TriggerInfo triggerInfo = new TaskInfo.TriggerInfo();
|
||||
triggerInfo.setCronExpression(cronExpression);
|
||||
triggerInfo.setRepeatCount(-1);
|
||||
triggerInfo.setDisallowConcurrentExecution(true);
|
||||
|
||||
Map<String, String> properties = new HashMap<>();
|
||||
properties.put(TENANT_ID, String.valueOf(tenantId));
|
||||
|
||||
if (!taskManager.isTaskScheduled(TASK_NAME_DELETION)) {
|
||||
TaskInfo taskInfo = new TaskInfo(TASK_NAME_DELETION, taskClazz, properties, triggerInfo);
|
||||
taskManager.registerTask(taskInfo);
|
||||
taskManager.rescheduleTask(taskInfo.getName());
|
||||
} else {
|
||||
throw new ArchivalTaskException("Data deletion task is already started for this tenant " +
|
||||
tenantId);
|
||||
}
|
||||
} catch (TaskException e) {
|
||||
throw new ArchivalTaskException("Error occurred while creating the task for tenant " + tenantId, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.task.impl;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.wso2.carbon.device.mgt.core.archival.ArchivalException;
|
||||
import org.wso2.carbon.device.mgt.core.archival.ArchivalService;
|
||||
import org.wso2.carbon.device.mgt.core.archival.ArchivalServiceImpl;
|
||||
import org.wso2.carbon.ntask.core.Task;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
public class ArchivedDataDeletionTask implements Task {
|
||||
|
||||
private static Log log = LogFactory.getLog(ArchivedDataDeletionTask.class);
|
||||
|
||||
private ArchivalService archivalService;
|
||||
|
||||
@Override
|
||||
public void setProperties(Map<String, String> map) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
this.archivalService = new ArchivalServiceImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
log.info("Executing DataDeletionTask at " + new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(new Date()));
|
||||
long startTime = System.nanoTime();
|
||||
try {
|
||||
archivalService.deleteArchivedRecords();
|
||||
} catch (ArchivalException e) {
|
||||
log.error("An error occurred while executing DataDeletionTask", e);
|
||||
}
|
||||
long endTime = System.nanoTime();
|
||||
long difference = (endTime - startTime) / 1000000 * 1000;
|
||||
log.info("DataDeletionTask completed. Total execution time: " + difference + " seconds");
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
{{!
|
||||
Copyright (c) 2016, 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.
|
||||
}}
|
||||
{{unit "cdmf.unit.ui.title" pageTitle="Device Location"}}
|
||||
|
||||
{{#zone "breadcrumbs"}}
|
||||
<li>
|
||||
<a href="{{@app.context}}/">
|
||||
<i class="icon fw fw-home"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{@app.context}}/device-locations">
|
||||
Device Locations
|
||||
</a>
|
||||
</li>
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "content"}}
|
||||
{{unit "cdmf.unit.geo-devices"}}
|
||||
{{/zone}}
|
@ -0,0 +1,5 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"uri": "/device-locations",
|
||||
"layout": "cdmf.layout.default"
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
{{!
|
||||
Copyright (c) 2016, 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.
|
||||
}}
|
||||
|
||||
{{#zone "topCss"}}
|
||||
{{css "css/app.css" combine=false}}
|
||||
{{css "css/map.css" combine=false}}
|
||||
{{css "css/leaflet.css" combine=false}}
|
||||
{{css "css/L.Control.Locate.css" combine=false}}
|
||||
{{css "css/MarkerCluster.Default.css" combine=false}}
|
||||
{{css "css/leaflet_fullscreen/leaflet.fullscreen.css" combine=false}}
|
||||
{{css "css/leaflet/leaflet.draw.css" combine=false}}
|
||||
{{css "css/leaflet.awesome-markers.css" combine=false}}
|
||||
{{/zone}}
|
||||
|
||||
|
||||
<div class="map-wrapper">
|
||||
<div id="" style="height: 80vh;">
|
||||
<div id="map"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#zone "bottomJs" }}
|
||||
{{js "js/leaflet/leaflet.js" }}
|
||||
{{js "js/leaflet/leaflet.markercluster.js" }}
|
||||
{{js "js/leaflet/L.Control.Locate.js" }}
|
||||
{{js "js/leaflet/L.Control.Focus.js" }}
|
||||
{{js "js/leaflet/leaflet.groupedlayercontrol.js" }}
|
||||
{{js "js/leaflet/Leaflet.fullscreen.min.js" }}
|
||||
{{js "js/leaflet/Marker.Rotate.js" }}
|
||||
{{js "js/leaflet/leaflet.draw.js" }}
|
||||
{{js "js/leaflet.awesome-markers.js"}}
|
||||
{{js "js/typeahead.bundle.min.js" }}
|
||||
{{js "js/geo_remote.js" }}
|
||||
{{js "js/app.js" }}
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
initialLoad(false);
|
||||
});
|
||||
</script>
|
||||
{{/zone}}
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"version": "1.0.0"
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/* Compatible with Leaflet 0.7 */
|
||||
|
||||
@import url('font/locate-fa.woff');
|
||||
@import url('css/locate-fa.css');
|
||||
@import url('css/animation.css');
|
||||
|
||||
.leaflet-touch .leaflet-bar-part-single {
|
||||
-webkit-border-radius: 7px 7px 7px 7px;
|
||||
border-radius: 7px 7px 7px 7px;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.leaflet-control-locate a {
|
||||
font-size: 1.4em;
|
||||
margin-left: 1px;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
.leaflet-control-locate.active a {
|
||||
color: #2074B6;
|
||||
}
|
||||
|
||||
.leaflet-control-locate.active.following a {
|
||||
color: #FC8428;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-control-locate {
|
||||
box-shadow: none;
|
||||
border: 2px solid rgba(0,0,0,0.2);
|
||||
background-clip: padding-box;
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
/* Conditional stylesheet for IE. */
|
||||
@import url('css/locate-fa-ie7.css');
|
||||
|
||||
.leaflet-control-locate {
|
||||
border: 3px solid #999;
|
||||
}
|
||||
|
||||
.leaflet-control-locate a {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.leaflet-control-locate a:hover {
|
||||
background-color: #fff;
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
.marker-cluster-small {
|
||||
background-color: rgba(181, 226, 140, 0.6);
|
||||
}
|
||||
.marker-cluster-small div {
|
||||
background-color: rgba(110, 204, 57, 0.6);
|
||||
}
|
||||
|
||||
.marker-cluster-medium {
|
||||
background-color: rgba(241, 211, 87, 0.6);
|
||||
}
|
||||
.marker-cluster-medium div {
|
||||
background-color: rgba(240, 194, 12, 0.6);
|
||||
}
|
||||
|
||||
.marker-cluster-large {
|
||||
background-color: rgba(253, 156, 115, 0.6);
|
||||
}
|
||||
.marker-cluster-large div {
|
||||
background-color: rgba(241, 128, 23, 0.6);
|
||||
}
|
||||
|
||||
/* IE 6-8 fallback colors */
|
||||
.leaflet-oldie .marker-cluster-small {
|
||||
background-color: rgb(181, 226, 140);
|
||||
}
|
||||
.leaflet-oldie .marker-cluster-small div {
|
||||
background-color: rgb(110, 204, 57);
|
||||
}
|
||||
|
||||
.leaflet-oldie .marker-cluster-medium {
|
||||
background-color: rgb(241, 211, 87);
|
||||
}
|
||||
.leaflet-oldie .marker-cluster-medium div {
|
||||
background-color: rgb(240, 194, 12);
|
||||
}
|
||||
|
||||
.leaflet-oldie .marker-cluster-large {
|
||||
background-color: rgb(253, 156, 115);
|
||||
}
|
||||
.leaflet-oldie .marker-cluster-large div {
|
||||
background-color: rgb(241, 128, 23);
|
||||
}
|
||||
|
||||
.marker-cluster {
|
||||
background-clip: padding-box;
|
||||
border-radius: 20px;
|
||||
}
|
||||
.marker-cluster div {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin-left: 5px;
|
||||
margin-top: 5px;
|
||||
|
||||
text-align: center;
|
||||
border-radius: 15px;
|
||||
font: 12px "Helvetica Neue", Arial, Helvetica, sans-serif;
|
||||
}
|
||||
.marker-cluster span {
|
||||
line-height: 30px;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
.leaflet-cluster-anim .leaflet-marker-icon, .leaflet-cluster-anim .leaflet-marker-shadow {
|
||||
-webkit-transition: -webkit-transform 0.3s ease-out, opacity 0.3s ease-in;
|
||||
-moz-transition: -moz-transform 0.3s ease-out, opacity 0.3s ease-in;
|
||||
-o-transition: -o-transform 0.3s ease-out, opacity 0.3s ease-in;
|
||||
transition: transform 0.3s ease-out, opacity 0.3s ease-in;
|
||||
}
|
@ -0,0 +1,151 @@
|
||||
input[type="radio"], input[type="checkbox"] {
|
||||
margin: 0;
|
||||
}
|
||||
.map-wrapper{
|
||||
background: #37474f;
|
||||
}
|
||||
#left_side_pannel> .nav > li > a{
|
||||
color: #fff;
|
||||
}
|
||||
.typeahead {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
#map {
|
||||
width: auto;
|
||||
height: 100%;
|
||||
}
|
||||
#loading {
|
||||
position: absolute;
|
||||
width: 220px;
|
||||
height: 19px;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin: -10px 0 0 -110px;
|
||||
z-index: 20001;
|
||||
}
|
||||
/*.sidebar-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
.sidebar-table {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 124px;
|
||||
bottom: 0px;
|
||||
overflow: auto;
|
||||
}*/
|
||||
.leaflet-control-layers label {
|
||||
font-weight: normal;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.leaflet-control-layers-group-name {
|
||||
font-weight: bold;
|
||||
margin-bottom: .2em;
|
||||
display: block;
|
||||
}
|
||||
.leaflet-control-layers-group {
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
.leaflet-control-layers-group label {
|
||||
padding-left: .5em;
|
||||
}
|
||||
.table {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.tt-dropdown-menu {
|
||||
background-color: #FFFFFF;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
border-radius: 4px 4px 4px 4px;
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
|
||||
margin-top: 4px;
|
||||
padding: 4px 0;
|
||||
width: 100%;
|
||||
max-height: 300px;
|
||||
overflow: auto;
|
||||
}
|
||||
.tt-suggestion {
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
padding: 3px 10px;
|
||||
}
|
||||
.tt-suggestion.tt-cursor {
|
||||
background-color: #0097CF;
|
||||
color: #FFFFFF;
|
||||
cursor: pointer;
|
||||
}
|
||||
.tt-suggestion p {
|
||||
margin: 0;
|
||||
}
|
||||
.tt-suggestion + .tt-suggestion {
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
.typeahead-header {
|
||||
margin: 0 5px 5px 5px;
|
||||
padding: 3px 0;
|
||||
border-bottom: 2px solid #333;
|
||||
}
|
||||
.has-feedback .form-control-feedback {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
display: block;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
/*.navbar .navbar-brand {
|
||||
font-size: 18px;
|
||||
}*/
|
||||
}
|
||||
@media (max-width: 767px){
|
||||
.url-break {
|
||||
word-break: break-all;
|
||||
word-break: break-word;
|
||||
-webkit-hyphens: auto;
|
||||
hyphens: auto;
|
||||
}
|
||||
#sidebar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.leaflet-geo-alerts{
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
background-color: white;
|
||||
padding: 5px;
|
||||
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
|
||||
width: 200px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.leaflet-geo-alerts a{
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
!* Print Handling *!
|
||||
@media print {
|
||||
.navbar {
|
||||
display: none !important;
|
||||
}
|
||||
.leaflet-control-container {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.nav > li > a {
|
||||
padding: 25px 15px !important;
|
||||
}
|
||||
|
||||
.nav > li > a:hover, .nav > li > a:focus {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
*/
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,19 @@
|
||||
Copyright (C) 2013 Panopta, Andrew Moffat
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,182 @@
|
||||
/* WIZARD GENERAL */
|
||||
.wizard {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.wizard-dialog {}
|
||||
.wizard-content {}
|
||||
|
||||
.wizard-body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* WIZARD HEADER */
|
||||
.wizard-header {
|
||||
padding: 9px 15px;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.wizard-header h3 {
|
||||
margin: 0;
|
||||
line-height: 35px;
|
||||
display: inline;
|
||||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
font-family: inherit;
|
||||
font-weight: bold;
|
||||
text-rendering: optimizelegibility;
|
||||
color: rgb(51, 51, 51);
|
||||
}
|
||||
|
||||
.wizard-subtitle {
|
||||
font-weight:bold;
|
||||
color:#AFAFAF;
|
||||
padding-left:20px;
|
||||
}
|
||||
|
||||
|
||||
/* WIZARD NAVIGATION */
|
||||
.wizard-steps {
|
||||
width: 28%;
|
||||
background-color: #f5f5f5;
|
||||
border-bottom-left-radius: 6px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.wizard-nav-container {
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
|
||||
.wizard-nav-list {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.wizard-nav-link .glyphicon-chevron-right {
|
||||
float:right;
|
||||
margin-top:12px;
|
||||
margin-right:-6px;
|
||||
opacity:.25;
|
||||
}
|
||||
|
||||
li.wizard-nav-item.active .glyphicon-chevron-right {
|
||||
opacity:1;
|
||||
}
|
||||
|
||||
li.wizard-nav-item {
|
||||
line-height:40px;
|
||||
}
|
||||
|
||||
.wizard-nav-list > li > a {
|
||||
background-color:#f5f5f5;
|
||||
padding:3px 15px 3px 20px;
|
||||
cursor:default;
|
||||
color:#B4B4B4;
|
||||
}
|
||||
|
||||
.wizard-nav-list > li > a:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.wizard-nav-list > li.already-visited > a.wizard-nav-link {
|
||||
color:#08C;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.wizard-nav-list > li.active > a.wizard-nav-link {
|
||||
color:white;
|
||||
}
|
||||
|
||||
.wizard-nav-item .already-visited .active {
|
||||
background-color:#08C;
|
||||
}
|
||||
|
||||
.wizard-nav-list li.active > a {
|
||||
background-color:#08C;
|
||||
}
|
||||
|
||||
|
||||
/* WIZARD CONTENT */
|
||||
.wizard-body form {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* WIZARD PROGRESS BAR */
|
||||
.wizard-progress-container {
|
||||
margin-top: 20px;
|
||||
padding: 15px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.wizard-card-container {
|
||||
margin-left: 28%;
|
||||
}
|
||||
|
||||
/* WIZARD CARDS */
|
||||
.wizard-error,
|
||||
.wizard-failure,
|
||||
.wizard-success,
|
||||
.wizard-loading,
|
||||
.wizard-card {
|
||||
border-top: 1px solid #EEE;
|
||||
display:none;
|
||||
padding:35px;
|
||||
padding-top:20px;
|
||||
overflow-y:auto;
|
||||
|
||||
/*
|
||||
position:relative;
|
||||
height:300px;
|
||||
margin-right: 5px;
|
||||
*/
|
||||
}
|
||||
|
||||
.wizard-card-overlay {
|
||||
overflow-y: initial;
|
||||
}
|
||||
|
||||
.wizard-card > h3 {
|
||||
margin-top:0;
|
||||
margin-bottom:20px;
|
||||
font-size:21px;
|
||||
line-height:40px;
|
||||
font-weight:normal;
|
||||
}
|
||||
|
||||
/* WIZARD FOOTER */
|
||||
.wizard-footer {
|
||||
padding:0;
|
||||
}
|
||||
|
||||
.wizard-buttons-container {
|
||||
padding:20px;
|
||||
}
|
||||
|
||||
.wizard-cancel {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
/* Inner Card */
|
||||
.wizard-input-section {
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
.wizard-dialog .popover.error-popover {
|
||||
background-color:#F2DEDE;
|
||||
color:#B94A48;
|
||||
border-color:#953B39;
|
||||
}
|
||||
|
||||
.wizard-dialog .popover.error-popover .arrow::after {
|
||||
border-right-color:#F2DEDE;
|
||||
}
|
||||
|
||||
.wizard-dialog .popover.error-popover .popover-title {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.wizard-dialog .popover.error-popover .arrow {
|
||||
border-right-color:#953B39;
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,85 @@
|
||||
/*
|
||||
Animation example, for spinners
|
||||
*/
|
||||
.animate-spin:before {
|
||||
-moz-animation: spin 2s infinite linear;
|
||||
-o-animation: spin 2s infinite linear;
|
||||
-webkit-animation: spin 2s infinite linear;
|
||||
animation: spin 2s infinite linear;
|
||||
display: inline-block;
|
||||
}
|
||||
@-moz-keyframes spin {
|
||||
0% {
|
||||
-moz-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-moz-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg);
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes spin {
|
||||
0% {
|
||||
-moz-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-moz-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg);
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
@-o-keyframes spin {
|
||||
0% {
|
||||
-moz-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-moz-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg);
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
@-ms-keyframes spin {
|
||||
0% {
|
||||
-moz-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-moz-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg);
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
@keyframes spin {
|
||||
0% {
|
||||
-moz-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-moz-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg);
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
|
||||
.icon-location:before { content: '\e802'; } /* '' */
|
||||
.icon-direction:before { content: '\e800'; } /* '' */
|
||||
.icon-spinner:before { content: '\e801'; } /* '' */
|
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue