/**
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
*
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
* graphic logo is a trademark of OpenMRS Inc.
*/
package org.openmrs.module.xforms;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.GZIPOutputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.api.context.Context;
import org.openmrs.api.context.ContextAuthenticationException;
import org.openmrs.module.xforms.download.PatientDownloadManager;
import org.openmrs.module.xforms.download.UserDownloadManager;
import org.openmrs.module.xforms.download.XformDataUploadManager;
import org.openmrs.module.xforms.download.XformDownloadManager;
import com.jcraft.jzlib.JZlib;
import com.jcraft.jzlib.ZOutputStream;
/**
* Serves xform services to non HTTP connections. Examples of such connections
* can be SMS, Bluetooth, Data cable, etc.
*
* @author Daniel
*
*/
public class XformsServer {
/** Value representing a not yet set status. */
public static final byte STATUS_NULL = -1;
/** Value representing success of an action. */
public static final byte STATUS_SUCCESS = 1;
/** Value representing failure of an action. */
public static final byte STATUS_FAILURE = 0;
/** Action to get a list of form definitions. */
public static final byte ACTION_DOWNLOAD_FORMS = 3;
/** Action to save a list of form data. */
public static final byte ACTION_UPLOAD_FORMS = 5;
/** Action to download a list of patients from the server. */
public static final byte ACTION_DOWNLOAD_PATIENTS = 6;
/** Action to download a list of users from the server. */
public static final byte ACTION_DOWNLOAD_USERS = 7;
/** Action to download a list of users and forms from the server. */
public static final byte ACTION_DOWNLOAD_COHORTS = 8;
/** Action to download a list of users and forms from the server. */
public static final byte ACTION_DOWNLOAD_SAVED_SEARCHES = 9;
/** Action to download a list of patients from the server. */
public static final byte ACTION_DOWNLOAD_SS_PATIENTS = 10;
/** Action to download a list of users and forms from the server. */
public static final byte ACTION_DOWNLOAD_USERS_AND_FORMS = 11;
/** Action to download a list of patients filtered by name and identifier. */
public static final byte ACTION_DOWNLOAD_FILTERED_PATIENTS = 15;
private Log log = LogFactory.getLog(this.getClass());
public XformsServer() {
}
/**
* Called when a new connection has been received. Failures are not handled
* in this class as different servers (BT,SMS, etc) may want to handle them
* differently.
*
* @param dis - the stream to read from.
* @param dos - the stream to write to.
*/
public void processConnection(DataInputStream dis, DataOutputStream dosParam)
throws IOException, Exception {
GZIPOutputStream gzip = new GZIPOutputStream(new BufferedOutputStream(dosParam));
DataOutputStream dos = new DataOutputStream(gzip);
byte responseStatus = ResponseStatus.STATUS_ERROR;
try{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
String name = dis.readUTF();
String pw = dis.readUTF();
String serializer = dis.readUTF();
@SuppressWarnings("unused")
String locale = dis.readUTF();
byte action = dis.readByte();
Context.openSession();
try{
Context.authenticate(name, pw);
}
catch(ContextAuthenticationException ex){
responseStatus = ResponseStatus.STATUS_ACCESS_DENIED;
}
if(responseStatus != ResponseStatus.STATUS_ACCESS_DENIED){
DataOutputStream dosTemp = new DataOutputStream(baos);
if (action == ACTION_DOWNLOAD_PATIENTS)
downloadPatients(String.valueOf(dis.readInt()), dosTemp,serializer, false);
else if(action == ACTION_DOWNLOAD_SS_PATIENTS)
downloadPatients(String.valueOf(dis.readInt()), dosTemp,serializer, true);
else if(action == ACTION_DOWNLOAD_COHORTS)
PatientDownloadManager.downloadCohorts(dosTemp,serializer);
else if(action == ACTION_DOWNLOAD_SAVED_SEARCHES)
PatientDownloadManager.downloadSavesSearches(dosTemp, serializer);
else if (action == ACTION_DOWNLOAD_FORMS)
XformDownloadManager.downloadXforms(dosTemp,serializer);
else if (action == ACTION_UPLOAD_FORMS)
submitXforms(dis, dosTemp,serializer);
else if (action == ACTION_DOWNLOAD_USERS)
UserDownloadManager.downloadUsers(dosTemp,serializer);
else if (action == ACTION_DOWNLOAD_USERS_AND_FORMS)
downloadUsersAndForms(dosTemp,serializer);
else if(action == ACTION_DOWNLOAD_FILTERED_PATIENTS)
downloadPatients(dis.readUTF(), dis.readUTF(), dosTemp,serializer);
responseStatus = ResponseStatus.STATUS_SUCCESS;
}
dos.writeByte(responseStatus);
if(responseStatus == ResponseStatus.STATUS_SUCCESS)
dos.write(baos.toByteArray());
dos.close();
gzip.finish();
}
catch(Exception ex){
log.error(ex.getMessage(),ex);
try{
dos.writeByte(responseStatus);
dos.flush();
gzip.finish();
}
catch(Exception e){
e.printStackTrace();
}
}
finally{
Context.closeSession();
}
}
private void downloadPatients(String cohortId, OutputStream os, String serializer, boolean isSavedSearch) throws Exception{
//Context.openSession();
try{
PatientDownloadManager.downloadPatients(cohortId, os, serializer, isSavedSearch);
}
finally{
//Context.closeSession();
}
}
private void downloadPatients(String name, String identifier, OutputStream os, String serializerKey) throws Exception{
//Context.openSession();
try{
PatientDownloadManager.downloadPatients(name, identifier, os,serializerKey);
}
finally{
//Context.closeSession();
}
}
/**
* Saves xforms xml models.
*
* @param dis - the stream to read from.
* @param dos - the stream to write to.
*/
private void submitXforms(DataInputStream dis, DataOutputStream dos, String serializerKey) throws Exception {
XformDataUploadManager.submitXforms(dis, new java.util.Date().toString(),serializerKey);
try {
dos.writeByte(STATUS_SUCCESS);
} catch (Exception e) {
log.error(e.getMessage(),e);
dos.writeByte(STATUS_FAILURE);
}
}
/**
* Downloads a list of users and xforms.
*
* @param dos - the stream to write to.
* @throws Exception
*/
private void downloadUsersAndForms(DataOutputStream dos, String serializerKey) throws Exception {
//Need to have a away of handing user serialization more smartly
UserDownloadManager.downloadUsers(dos,null);
XformDownloadManager.downloadXforms(dos,serializerKey);
}
}