Issue #2385 Add capability to backup/restore data delivery subscriptions

Change-Id: I281dcf3259f3db50feabef40574bdb4487c95c7e

Former-commit-id: 7eb5c27fcbcd4fb52e9776e5ed2e6f16248922e1
This commit is contained in:
Benjamin Phillippe 2013-09-20 10:13:09 -05:00
parent 051a83e8f4
commit 1d2b59c0a2
3 changed files with 453 additions and 0 deletions

View file

@ -22,6 +22,7 @@ package com.raytheon.uf.common.registry.services.rest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.xml.bind.JAXBException;
import com.raytheon.uf.common.registry.RegistryException;
import com.raytheon.uf.common.registry.services.rest.response.RestCollectionResponse;
@ -37,6 +38,7 @@ import com.raytheon.uf.common.registry.services.rest.response.RestCollectionResp
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 7/29/2013 2191 bphillip Initial implementation
* 9/20/2013 2385 bphillip Added subscription backup functions
* </pre>
*
* @author bphillip
@ -68,4 +70,74 @@ public interface IRegistryDataAccessService {
@Path("/rest/dataAccess/removeSubscriptionsFor/{siteId}")
public void removeSubscriptionsForSite(@PathParam("siteId") String siteId)
throws RegistryException;
/**
* Gets the subscriptions that are currently in the registry and formats
* them in HTML for viewing in a web browser
*
* @return The page containing the subscriptions
*/
@GET
@Path("/rest/dataAccess/getSubscriptions")
public String getSubscriptions();
/**
*
* Backs up the specified subscription to be restored at a later time
*
* @param subscriptionName
* The subscription to be backed up
* @return Status message about whether the backup was successful
* @throws JAXBException
* If marshalling/unmarshalling errors are encountered
*/
@GET
@Path("/rest/dataAccess/backupSubscription/{subscriptionName}")
public String backupSubscription(
@PathParam("subscriptionName") String subscriptionName)
throws JAXBException;
/**
* Backs up all subscriptions currently in the registry
*
* @return Status message about whether the backup was successful
* @throws JAXBException
* If marshalling/unmarshalling errors are encountered
*/
@GET
@Path("/rest/dataAccess/backupAllSubscriptions/")
public String backupAllSubscriptions() throws JAXBException;
/**
* Restores the specified subscription
*
* @param subscriptionName
* The name of the subscription to restore
* @return Status message about whether the backup was successful
* @throws JAXBException
*/
@GET
@Path("/rest/dataAccess/restoreSubscription/{subscriptionName}")
public String restoreSubscription(
@PathParam("subscriptionName") String subscriptionName)
throws JAXBException;
/**
* Restores any subscriptions that were previously backed up
*
* @return Status messages relating to the success or failure of the restore
*/
@GET
@Path("/rest/dataAccess/restoreSubscriptions/")
public String restoreSubscriptions();
/**
* Clears the backup file directory
*
* @return Status message
*/
@GET
@Path("/rest/dataAccess/clearSubscriptionBackupFiles/")
public String clearSubscriptionBackupFiles();
}

View file

@ -19,16 +19,23 @@
**/
package com.raytheon.uf.edex.registry.ebxml.services.rest;
import java.io.File;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.xml.bind.JAXBException;
import oasis.names.tc.ebxml.regrep.wsdl.registry.services.v4.LifecycleManager;
import oasis.names.tc.ebxml.regrep.wsdl.registry.services.v4.MsgRegistryException;
import oasis.names.tc.ebxml.regrep.xsd.lcm.v4.Mode;
import oasis.names.tc.ebxml.regrep.xsd.lcm.v4.RemoveObjectsRequest;
import oasis.names.tc.ebxml.regrep.xsd.lcm.v4.SubmitObjectsRequest;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.ObjectRefListType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.ObjectRefType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.RegistryObjectListType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.RegistryObjectType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.SubscriptionType;
import org.springframework.transaction.annotation.Transactional;
@ -36,6 +43,7 @@ import org.springframework.transaction.annotation.Transactional;
import com.raytheon.uf.common.registry.RegistryException;
import com.raytheon.uf.common.registry.services.rest.IRegistryDataAccessService;
import com.raytheon.uf.common.registry.services.rest.response.RestCollectionResponse;
import com.raytheon.uf.common.serialization.JAXBManager;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.edex.registry.ebxml.dao.RegistryObjectDao;
@ -51,6 +59,7 @@ import com.raytheon.uf.edex.registry.ebxml.dao.RegistryObjectDao;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 7/29/2013 2191 bphillip Initial implementation
* 9/20/2013 2385 bphillip Added subscription backup functions
* </pre>
*
* @author bphillip
@ -63,12 +72,24 @@ public class RegistryDataAccessService implements IRegistryDataAccessService {
private static final IUFStatusHandler statusHandler = UFStatus
.getHandler(RegistryDataAccessService.class);
private static final File SUBSCRIPTION_BACKUP_DIR = new File(
System.getProperty("edex.home")
+ "/data/registrySubscriptionBackup");
private static final String GET_SUBSCRIPTIONS_QUERY = "FROM RegistryObjectType obj where lower(obj.objectType) like '%subscription%' order by obj.id asc";
/** Data access object for registry objects */
private RegistryObjectDao registryObjectDao;
/** Lifecyclemanager */
private LifecycleManager lcm;
/**
* @see
* com.raytheon.uf.common.registry.services.rest.IRegistryDataAccessService
* .getRegistryObjectIdsOfType(String)
*/
@Override
@GET
@Path("/rest/dataAccess/getRegistryObjectIds/{objectType}")
public RestCollectionResponse<String> getRegistryObjectIdsOfType(
@ -81,6 +102,12 @@ public class RegistryDataAccessService implements IRegistryDataAccessService {
return response;
}
/**
* @see
* com.raytheon.uf.common.registry.services.rest.IRegistryDataAccessService
* .removeSubscriptionsForSite(String)
*/
@Override
@GET
@Path("/rest/dataAccess/removeSubscriptionsFor/{siteId}")
public void removeSubscriptionsForSite(@PathParam("siteId") String siteId) {
@ -112,6 +139,224 @@ public class RegistryDataAccessService implements IRegistryDataAccessService {
}
}
/**
* @see
* com.raytheon.uf.common.registry.services.rest.IRegistryDataAccessService
* .getSubscriptions()
*/
@Override
@GET
@Path("/rest/dataAccess/getSubscriptions")
public String getSubscriptions() {
String[] slotNames = new String[] { "name", "owner", "dataSetName",
"provider", "dataSetType", "route", "active", "groupName",
"valid", "fullDataSet" };
StringBuilder response = new StringBuilder();
response.append("<table border=\"1\" style=\"border-style:solid; border-width:thin\"> ");
response.append("<tr>");
response.append("<th>ID</th>");
for (String slotName : slotNames) {
response.append("<th>").append(slotName).append("</th>");
}
response.append("</tr>");
List<RegistryObjectType> subs = registryObjectDao
.executeHQLQuery(GET_SUBSCRIPTIONS_QUERY);
for (RegistryObjectType obj : subs) {
String[] values = new String[slotNames.length + 1];
values[0] = obj.getId();
for (int i = 0; i < slotNames.length; i++) {
values[i + 1] = String.valueOf(obj.getSlotValue(slotNames[i]));
}
response.append("<tr>");
for (String val : values) {
response.append("<td>").append(val).append("</td>");
}
response.append("</tr>");
}
response.append("</table>");
return response.toString();
}
/**
* @see
* com.raytheon.uf.common.registry.services.rest.IRegistryDataAccessService
* .backupSubscription(String)
*/
@Override
@GET
@Path("/rest/dataAccess/backupSubscription/{subscriptionName}")
public String backupSubscription(
@PathParam("subscriptionName") String subscriptionName)
throws JAXBException {
StringBuilder response = new StringBuilder();
RegistryObjectType sub = registryObjectDao.getById(subscriptionName);
if (sub == null) {
response.append("Subscription with ID [").append(subscriptionName)
.append("] not found in registry");
} else {
if (!SUBSCRIPTION_BACKUP_DIR.exists()) {
SUBSCRIPTION_BACKUP_DIR.mkdirs();
}
JAXBManager jaxb = new JAXBManager(SubmitObjectsRequest.class);
String subId = sub.getId();
File backupFile = new File(SUBSCRIPTION_BACKUP_DIR.getPath()
+ File.separator + subId);
SubmitObjectsRequest submitObjectsRequest = new SubmitObjectsRequest();
submitObjectsRequest.setCheckReferences(false);
submitObjectsRequest
.setComment("Restoring backed up subscriptions");
submitObjectsRequest.setId("Restore subscription [" + subId + "]");
submitObjectsRequest.setMode(Mode.CREATE_OR_REPLACE);
submitObjectsRequest
.setRegistryObjectList(new RegistryObjectListType());
submitObjectsRequest.getRegistryObjects().add(sub);
try {
jaxb.getJaxbContext().createMarshaller()
.marshal(submitObjectsRequest, backupFile);
} catch (JAXBException e) {
statusHandler.error("Error backing up subscription [" + subId
+ "]", e);
response.append("Error backing up subscription [")
.append(subId).append("]<br>");
}
response.append("Subscription [").append(subId)
.append("] successfully backed up to [")
.append(backupFile.getPath()).append("]<br>");
}
return response.toString();
}
/**
* @see
* com.raytheon.uf.common.registry.services.rest.IRegistryDataAccessService
* .backupAllSubscriptions()
*/
@Override
@GET
@Path("/rest/dataAccess/backupAllSubscriptions/")
public String backupAllSubscriptions() throws JAXBException {
StringBuilder response = new StringBuilder();
List<RegistryObjectType> subs = registryObjectDao
.executeHQLQuery(GET_SUBSCRIPTIONS_QUERY);
if (subs.isEmpty()) {
response.append("No subscriptions present to backup!");
} else {
for (RegistryObjectType sub : subs) {
response.append(backupSubscription(sub.getId()));
}
}
return response.toString();
}
/**
* @see
* com.raytheon.uf.common.registry.services.rest.IRegistryDataAccessService
* .restoreSubscription(String)
*/
@Override
@GET
@Path("/rest/dataAccess/restoreSubscription/{subscriptionName}")
public String restoreSubscription(
@PathParam("subscriptionName") String subscriptionName)
throws JAXBException {
StringBuilder response = new StringBuilder();
File subscriptionFile = new File(SUBSCRIPTION_BACKUP_DIR
+ File.separator + subscriptionName);
if (subscriptionFile.exists()) {
JAXBManager jaxb = new JAXBManager(SubmitObjectsRequest.class);
SubmitObjectsRequest submitRequest = (SubmitObjectsRequest) jaxb
.getJaxbContext().createUnmarshaller()
.unmarshal(subscriptionFile);
try {
lcm.submitObjects(submitRequest);
} catch (MsgRegistryException e) {
response.append("Error restoring subscription from file [")
.append(subscriptionFile).append("] ")
.append(e.getMessage()).append("<br>");
statusHandler.error("Error restoring subscription from file ["
+ subscriptionFile + "]", e);
return response.toString();
}
subscriptionFile.delete();
response.append("Subscription successfully restored from file [")
.append(subscriptionFile).append("]<br>");
} else {
response.append("No backup file exists for subscription[")
.append(subscriptionName).append("]<br>");
}
return response.toString();
}
/**
* @see
* com.raytheon.uf.common.registry.services.rest.IRegistryDataAccessService
* .restoreSubscriptions()
*/
@Override
@GET
@Path("/rest/dataAccess/restoreSubscriptions/")
public String restoreSubscriptions() {
StringBuilder response = new StringBuilder();
if (SUBSCRIPTION_BACKUP_DIR.exists()) {
File[] filesToRestore = SUBSCRIPTION_BACKUP_DIR.listFiles();
if (filesToRestore.length == 0) {
response.append("No subscriptions found to restore<br>");
} else {
for (File subscription : filesToRestore) {
try {
response.append(restoreSubscription(subscription
.getName()));
} catch (JAXBException e) {
statusHandler.error("Error restoring subscription ["
+ subscription + "]", e);
response.append("Error restoring subscription [")
.append(subscription).append("] ")
.append(e.getMessage()).append("<br>");
continue;
}
}
}
} else {
response.append("No subscriptions found to restore<br>");
}
return response.toString();
}
/**
* @see
* com.raytheon.uf.common.registry.services.rest.IRegistryDataAccessService
* .clearSubscriptionBackupFiles()
*/
@GET
@Path("/rest/dataAccess/clearSubscriptionBackupFiles/")
public String clearSubscriptionBackupFiles() {
StringBuilder response = new StringBuilder();
if (SUBSCRIPTION_BACKUP_DIR.exists()) {
File[] filesToDelete = SUBSCRIPTION_BACKUP_DIR.listFiles();
if (filesToDelete.length == 0) {
response.append("No backup files to delete");
}
for (File file : filesToDelete) {
if (file.delete()) {
response.append("Deleted backup file [")
.append(file.getPath()).append("]<br>");
} else {
response.append("Error deleting backup file [")
.append(file.getPath()).append("]<br>");
}
}
} else {
response.append("No backup files to delete");
}
return response.toString();
}
public void setRegistryObjectDao(RegistryObjectDao registryObjectDao) {
this.registryObjectDao = registryObjectDao;
}

View file

@ -0,0 +1,136 @@
<html>
<head>
<style type="text/css">
a {font-weight:bold;}
td {width:200px;}
button {width:190px;}
input{width:300px;}
table {border:0;}
select {width:200px;}
body { font-family: Helvetica;
margin-left: 75px;
margin-right: 75px;
background: #D3D3D3;}
</style>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<script type="text/javascript" src='/dwr/engine.js'></script>
<script type="text/javascript" src='/dwr/util.js'></script>
<title>Backup/Restore Subscriptions</title>
</head>
<body>
<h3>BACKUP/RESTORE DATA DELIVERY SUBSCRIPTIONS</h3>
<table>
<tr>
<td>
<button id="backupSubscriptionButton" onClick="backupSubscription()" >Backup Subscription</button>
</td>
<td>
<input id="backupSubscriptionText" type="text"/></td>
</td>
</tr>
<tr>
<td>
<button id="backupAllSubscriptionsButton" onClick="backupAllSubscriptions()">Backup All Subscriptions</button>
</td>
<td>
</td>
</tr>
<tr>
<td>
<button id="restoreSubscriptionButton" onClick="restoreSubscription()" >Restore Subscription</button>
</td>
<td>
<input id="restoreSubscriptionText" type="text"/></td>
</td>
</tr>
<tr>
<td>
<button id="restoreSubscriptionsButton" onClick="restoreSubscriptions()">Restore Subscriptions</button>
</td>
<td>
</td>
</tr>
<tr>
<td>
<button id="viewSubscriptionsButton" onClick="viewSubscriptions()">View Subscriptions</button>
</td>
<td>
</td>
</tr>
<tr>
<td>
<button id="clearBackedUpSubscriptionsButton" onClick="clearBackupDir()">Clear Backup Files</button>
</td>
<td>
</td>
</tr>
</table>
<p>
<p>
<div id="statusSpan" style="font-weight:bold; font-size:8pt"></span>
<br>
</body>
<script language="JavaScript">
function clearBackupDir(){
updateStatus("Clearing backup files...")
updateStatus(callRESTService("clearSubscriptionBackupFiles"))
}
function viewSubscriptions(){
updateStatus("Retrieving Subscriptions...")
updateStatus(callRESTService("getSubscriptions"))
}
function restoreSubscription(){
subscription = document.getElementById("restoreSubscriptionText").value
if(subscription){
updateStatus("Restoring subscription: ["+subscription+"]...")
updateStatus(callRESTService("restoreSubscription/"+subscription))
}else{
updateStatus("Please input a subscription name to be restored")
}
}
function restoreSubscriptions(){
updateStatus("Restoring Subscriptions...")
updateStatus(callRESTService("restoreSubscriptions"))
}
function backupSubscription(){
subscription = document.getElementById("backupSubscriptionText").value
if(subscription){
updateStatus("Backing up subscription: ["+subscription+"]...")
updateStatus(callRESTService("backupSubscription/"+subscription))
}else{
updateStatus("Please input a subscription name to be backed up")
}
}
function backupAllSubscriptions(){
updateStatus("Backing up subscriptions...")
updateStatus(callRESTService("backupAllSubscriptions"))
}
function callRESTService(func){
var url = "http://"+window.location.host+"/rest/dataAccess/"+func;
var client = new XMLHttpRequest();
client.open("GET", url, false);
client.setRequestHeader("Content-Type", "text/plain");
client.send();
return client.responseText
}
function updateStatus(status){
document.getElementById("statusSpan").innerHTML = status
}
</script>
</html>