/**
* The contents of this file are subject to the OpenMRS Public License
* Version 1.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://license.openmrs.org
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* Copyright (C) OpenMRS, LLC. All Rights Reserved.
*/
package org.openmrs.module.sync.web.dwr;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Date;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.api.context.Context;
import org.openmrs.module.sync.SyncConstants;
import org.openmrs.module.sync.SyncItem;
import org.openmrs.module.sync.SyncRecord;
import org.openmrs.module.sync.SyncTransmissionState;
import org.openmrs.module.sync.SyncUtil;
import org.openmrs.module.sync.SyncUtilTransmission;
import org.openmrs.module.sync.SyncUtilTransmission.ReceivingSize;
import org.openmrs.module.sync.api.SyncService;
import org.openmrs.module.sync.ingest.SyncTransmissionResponse;
import org.openmrs.module.sync.serialization.ZipPackage;
import org.openmrs.module.sync.server.ConnectionResponse;
import org.openmrs.module.sync.server.ServerConnection;
import org.openmrs.module.sync.server.ServerConnectionState;
/**
* DWR methods used by the sync module
*/
public class DWRSyncService {
protected final Log log = LogFactory.getLog(getClass());
/**
* Used when doing a full synchronize to get the number of objects the parent server is sending
* down to us before the actual update is done
*/
private static ReceivingSize receivingSize = new ReceivingSize();
public SyncCloneItem cloneParentDB(String address, String username, String password) {
SyncCloneItem item = new SyncCloneItem();
if (address != null && address.length() > 0) {
File dir = SyncUtil.getSyncApplicationDir();
File file = new File(dir, SyncConstants.CLONE_IMPORT_FILE_NAME
+ SyncConstants.SYNC_FILENAME_MASK.format(new Date()) + ".sql");
ConnectionResponse connResponse = ServerConnection.cloneParentDB(address, username, password);
item.setConnectionState(connResponse.getState().toString());
item.setErrorMessage(connResponse.getErrorMessage());
// execute the parent's sql file on our database
if (ServerConnectionState.OK.equals(connResponse.getState())) {
byte sql[] = connResponse.getResponsePayload().getBytes(Charset.forName("UTF-8"));
try {
IOUtils.write(sql, new FileOutputStream(file));
Context.getService(SyncService.class).execGeneratedFile(file);
item.setResponsefileName(file.getName());
item.setErrorMessage("Parent data cloned successfully");
boolean clonedDBLog = Boolean.parseBoolean(Context.getAdministrationService()
.getGlobalProperty(SyncConstants.PROPERTY_SYNC_CLONED_DATABASE_LOG_ENABLED, "true"));
if (!clonedDBLog){
file.delete();
}
}
catch (FileNotFoundException e) {
item.setErrorMessage("Unable to save file(" + file.getAbsolutePath() + ")");
log.error("Unable to save file(" + file.getAbsolutePath() + ") : Error generated", e);
}
catch (IOException e) {
item.setErrorMessage("Unable to save file(" + file.getAbsolutePath() + ")");
log.error("Unable to save file(" + file.getAbsolutePath() + ") : Error generated", e);
}
}
}
return item;
}
/**
* Pings the given server with the given username/password to make sure the settings are correct
*
* @param address url to ping
* @param username username with which to log in
* @param password password with which to log in
* @return SyncConnectionTestItem that contains success or failure
*/
public SyncConnectionTestItem testConnection(String address, String username, String password) {
SyncConnectionTestItem item = new SyncConnectionTestItem();
item.setConnectionState(ServerConnectionState.NO_ADDRESS.toString());
if (address != null && address.length() > 0) {
ConnectionResponse connResponse = ServerConnection.test(address, username, password);
// constructor for SyncTransmissionResponse is null-safe
SyncTransmissionResponse str = new SyncTransmissionResponse(connResponse);
// constructor for SyncConnectionTestItem is null-safe
item = new SyncConnectionTestItem(str);
}
return item;
}
/**
* Call this method after initiating {@link #syncToParent()} to get the number of objects that
* the parent is sending to us. This value is updated mid-method for display to the end user.
*
* @return integer number of records being sent to us (or null if none)
*/
public Integer getNumberOfObjectsBeingReceived() {
return receivingSize.getSize();
}
/**
* Used by the status.list page to send data to the parent and show the results. <br/>
* Use #getNumberOfObjectsBeingReceived() before this method is done to know how many objects
* the parent is sending to our server.
*
* @return results of the transmission
*/
public SyncTransmissionResponseItem syncToParent() {
// the doFullSync method updates this 'objectsBeingReceived' so that the
// jsp page can know what we're dealing with
// before the whole SyncTransmissionsResponse is returned
SyncTransmissionResponse response = SyncUtilTransmission.doFullSynchronize(receivingSize,
SyncUtil.getGlobalPropetyValueAsInteger(SyncConstants.PROPERTY_NAME_MAX_RECORDS_WEB));
receivingSize.setSize(null); // reset variable
if (response != null) {
return new SyncTransmissionResponseItem(response);
} else {
SyncTransmissionResponseItem transmissionResponse = new SyncTransmissionResponseItem();
transmissionResponse.setErrorMessage(SyncConstants.ERROR_SEND_FAILED.toString());
transmissionResponse.setFileName(SyncConstants.FILENAME_SEND_FAILED);
transmissionResponse.setUuid(SyncConstants.UUID_UNKNOWN);
transmissionResponse.setTransmissionState(SyncTransmissionState.FAILED.toString());
return transmissionResponse;
}
}
public String getSyncItemContent(String guid, String key) {
String content = "";
StringBuilder contentBuilder = new StringBuilder();
Collection<SyncItem> itemList;
if (guid != null && guid != "" && key != null && key != "") {
SyncRecord syncRecord = Context.getService(SyncService.class).getSyncRecord(guid);
if (syncRecord != null ) {
itemList = syncRecord.getItems();
for (SyncItem item : itemList) {
if (item.getKey().getKeyValue().equals(key))
content = item.getContent();
}
}
/** building an ad-hoc xml document that contains the items and the payload, eg:
<syncRecord>
<org.openmrs.PatientIdentifier>...</org.openmrs.PatientIdentifier>
<payload>
<items><SyncItem containedType...
</items></>
</payload>
</syncRecord>
**/
if (StringUtils.isNotBlank(content)) {
contentBuilder.append("<syncRecord>").append(content);
contentBuilder.append("<payload>").append(SyncUtil.getSyncRecordPayload(syncRecord)).append("</payload>");
contentBuilder.append("</syncRecord>");
content = contentBuilder.toString();
}
}
return content;
}
public String setSyncRecordPayload(String guid, String key, String payload) {
String ret = "Error: Not saved";
if (guid != null && guid != "" && key != null && key != "") {
SyncRecord record = Context.getService(SyncService.class).getSyncRecord(guid);
if (StringUtils.isNotBlank(payload)) {
record.setItems(SyncUtil.getSyncItemsFromPayload(payload));
}
Context.getService(SyncService.class).updateSyncRecord(record);
ret = "Item payload saved";
}
return ret;
}
public String setSyncItemContent(String guid, String key, String content) {
String ret = "Error: Not saved";
Collection<SyncItem> itemList;
if (guid != null && guid != "" && key != null && key != "") {
itemList = Context.getService(SyncService.class).getSyncRecord(guid).getItems();
for (SyncItem item : itemList) {
if (item.getKey().getKeyValue().equals(key))
item.setContent(content);
}
SyncRecord record = Context.getService(SyncService.class).getSyncRecord(guid);
record.setItems(itemList);
Context.getService(SyncService.class).updateSyncRecord(record);
ret = "Item payload saved";
}
return ret;
}
public boolean archiveSyncJournal(boolean clearDir) {
return new ZipPackage(org.openmrs.util.OpenmrsUtil.getDirectoryInApplicationDataDirectory("sync"), "journal")
.zip(clearDir);
}
public boolean archiveSyncImport(boolean clearDir) {
return new ZipPackage(org.openmrs.util.OpenmrsUtil.getDirectoryInApplicationDataDirectory("sync"), "import")
.zip(clearDir);
}
}