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'; } /* '' */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue