use of org.opendatakit.briefcase.model.ParsingException in project briefcase by opendatakit.
the class XmlManipulationUtils method parseFormListResponse.
public static final List<RemoteFormDefinition> parseFormListResponse(boolean isOpenRosaResponse, Document formListDoc) throws ParsingException {
// This gets a list of available forms from the specified server.
List<RemoteFormDefinition> formList = new ArrayList<>();
if (isOpenRosaResponse) {
// Attempt OpenRosa 1.0 parsing
Element xformsElement = formListDoc.getRootElement();
if (!xformsElement.getName().equals("xforms")) {
log.error("Parsing OpenRosa reply -- root element is not <xforms> :" + xformsElement.getName());
throw new ParsingException(BAD_OPENROSA_FORMLIST);
}
String namespace = xformsElement.getNamespace();
if (!isXformsListNamespacedElement(xformsElement)) {
log.error("Parsing OpenRosa reply -- root element namespace is incorrect:" + namespace);
throw new ParsingException(BAD_OPENROSA_FORMLIST);
}
int nElements = xformsElement.getChildCount();
for (int i = 0; i < nElements; ++i) {
if (xformsElement.getType(i) != Element.ELEMENT) {
// e.g., whitespace (text)
continue;
}
Element xformElement = (Element) xformsElement.getElement(i);
if (!isXformsListNamespacedElement(xformElement)) {
// someone else's extension?
continue;
}
String name = xformElement.getName();
if (!name.equalsIgnoreCase("xform")) {
// someone else's extension?
continue;
}
// this is something we know how to interpret
String formId = null;
String formName = null;
String version = null;
String majorMinorVersion = null;
String description = null;
String downloadUrl = null;
String manifestUrl = null;
// don't process descriptionUrl
int fieldCount = xformElement.getChildCount();
for (int j = 0; j < fieldCount; ++j) {
if (xformElement.getType(j) != Element.ELEMENT) {
// whitespace
continue;
}
Element child = xformElement.getElement(j);
if (!isXformsListNamespacedElement(child)) {
// someone else's extension?
continue;
}
String tag = child.getName();
if (tag.equals("formID")) {
formId = XFormParser.getXMLText(child, true);
if (formId != null && formId.length() == 0) {
formId = null;
}
} else if (tag.equals("name")) {
formName = XFormParser.getXMLText(child, true);
if (formName != null && formName.length() == 0) {
formName = null;
}
} else if (tag.equals("version")) {
version = XFormParser.getXMLText(child, true);
if (version != null && version.length() == 0) {
version = null;
}
} else if (tag.equals("majorMinorVersion")) {
majorMinorVersion = XFormParser.getXMLText(child, true);
if (majorMinorVersion != null && majorMinorVersion.length() == 0) {
majorMinorVersion = null;
}
} else if (tag.equals("descriptionText")) {
description = XFormParser.getXMLText(child, true);
if (description != null && description.length() == 0) {
description = null;
}
} else if (tag.equals("downloadUrl")) {
downloadUrl = XFormParser.getXMLText(child, true);
if (downloadUrl != null && downloadUrl.length() == 0) {
downloadUrl = null;
}
} else if (tag.equals("manifestUrl")) {
manifestUrl = XFormParser.getXMLText(child, true);
if (manifestUrl != null && manifestUrl.length() == 0) {
manifestUrl = null;
}
}
}
if (formId == null || downloadUrl == null || formName == null) {
log.error("Parsing OpenRosa reply -- Forms list entry " + Integer.toString(i) + " is missing one or more tags: formId, name, or downloadUrl");
formList.clear();
throw new ParsingException(BAD_OPENROSA_FORMLIST);
}
String versionString = null;
if (version != null && version.length() != 0) {
versionString = version;
} else if (majorMinorVersion != null && majorMinorVersion.length() != 0) {
int idx = majorMinorVersion.indexOf(".");
if (idx == -1) {
versionString = majorMinorVersion;
} else {
versionString = majorMinorVersion.substring(0, idx);
}
}
try {
if (versionString != null) {
// verify that the version string is a long integer value...
Long.parseLong(versionString);
}
} catch (Exception e) {
log.error("Parsing OpenRosa reply -- Forms list entry " + Integer.toString(i) + " has an invalid version string: " + versionString, e);
formList.clear();
throw new ParsingException(BAD_OPENROSA_FORMLIST);
}
formList.add(new RemoteFormDefinition(formName, formId, versionString, downloadUrl, manifestUrl));
}
} else {
// Aggregate 0.9.x mode...
// populate HashMap with form names and urls
Element formsElement = formListDoc.getRootElement();
int formsCount = formsElement.getChildCount();
for (int i = 0; i < formsCount; ++i) {
if (formsElement.getType(i) != Element.ELEMENT) {
// whitespace
continue;
}
Element child = formsElement.getElement(i);
String tag = child.getName();
if (tag.equalsIgnoreCase("form")) {
String formName = XFormParser.getXMLText(child, true);
if (formName != null && formName.length() == 0) {
formName = null;
}
String downloadUrl = child.getAttributeValue(null, "url");
downloadUrl = downloadUrl.trim();
if (downloadUrl != null && downloadUrl.length() == 0) {
downloadUrl = null;
}
if (downloadUrl == null || formName == null) {
log.error("Parsing OpenRosa reply -- Forms list entry " + Integer.toString(i) + " is missing form name or url attribute");
formList.clear();
throw new ParsingException(BAD_LEGACY_FORMLIST);
}
// Since this is ODK Aggregate 0.9.8 or higher, we know that the
// formId is
// given as a parameter of the URL...
String formId = null;
try {
URL url = new URL(downloadUrl);
String qs = url.getQuery();
if (qs.startsWith(ODK_ID_PARAMETER_EQUALS)) {
formId = qs.substring(ODK_ID_PARAMETER_EQUALS.length());
}
} catch (MalformedURLException e) {
log.warn("bad download url", e);
}
if (formId == null) {
throw new ParsingException("Unable to extract formId from download URL of legacy 0.9.8 server");
}
formList.add(new RemoteFormDefinition(formName, formId, null, downloadUrl, null));
}
}
}
return formList;
}
use of org.opendatakit.briefcase.model.ParsingException in project briefcase by opendatakit.
the class ExportToCsv method doAction.
@Override
public boolean doAction() {
boolean allSuccessful = true;
File instancesDir;
try {
instancesDir = FileSystemUtils.getFormInstancesDirectory(briefcaseLfd.getFormDirectory());
} catch (FileSystemException e) {
String msg = "Unable to access instances directory of form";
log.error(msg, e);
EventBus.publish(new ExportProgressEvent(msg, briefcaseLfd));
return false;
}
if (!outputDir.exists()) {
if (!outputDir.mkdir()) {
EventBus.publish(new ExportProgressEvent("Unable to create destination directory", briefcaseLfd));
return false;
}
}
if (!processFormDefinition()) {
// weren't able to initialize the csv file...
return false;
}
File[] instances = instancesDir.listFiles(file -> file.isDirectory() && new File(file, "submission.xml").exists());
totalInstances = instances.length;
// assume it to be latest.
if (instances != null) {
Arrays.sort(instances, (f1, f2) -> {
try {
if (f1.isDirectory() && f2.isDirectory()) {
File submission1 = new File(f1, "submission.xml");
String submissionDate1String = XmlManipulationUtils.parseXml(submission1).getRootElement().getAttributeValue(null, "submissionDate");
File submission2 = new File(f2, "submission.xml");
String submissionDate2String = XmlManipulationUtils.parseXml(submission2).getRootElement().getAttributeValue(null, "submissionDate");
Date submissionDate1 = StringUtils.isNotEmptyNotNull(submissionDate1String) ? WebUtils.parseDate(submissionDate1String) : new Date();
Date submissionDate2 = StringUtils.isNotEmptyNotNull(submissionDate2String) ? WebUtils.parseDate(submissionDate2String) : new Date();
return submissionDate1.compareTo(submissionDate2);
}
} catch (ParsingException | FileSystemException e) {
log.error("failed to sort submissions", e);
}
return 0;
});
}
for (File instanceDir : instances) {
if (terminationFuture.isCancelled()) {
EventBus.publish(new ExportProgressEvent("Aborted", briefcaseLfd));
allSuccessful = false;
break;
}
if (instanceDir.getName().startsWith("."))
// Mac OSX
continue;
allSuccessful = allSuccessful && processInstance(instanceDir);
}
for (OutputStreamWriter w : fileMap.values()) {
try {
w.flush();
w.close();
} catch (IOException e) {
String msg = "Error flushing csv file";
EventBus.publish(new ExportProgressEvent(msg, briefcaseLfd));
log.error(msg, e);
allSuccessful = false;
}
}
return allSuccessful;
}
use of org.opendatakit.briefcase.model.ParsingException in project briefcase by opendatakit.
the class FileSystemUtils method decryptSubmissionFiles.
private static boolean decryptSubmissionFiles(String base64EncryptedSymmetricKey, FormInstanceMetadata fim, List<String> mediaNames, String encryptedSubmissionFile, String base64EncryptedElementSignature, PrivateKey rsaPrivateKey, File instanceDir, File unencryptedDir) throws FileSystemException, CryptoException, ParsingException {
EncryptionInformation ei = new EncryptionInformation(base64EncryptedSymmetricKey, fim.instanceId, rsaPrivateKey);
byte[] elementDigest;
try {
// construct the base64-encoded RSA-encrypted symmetric key
Cipher pkCipher;
pkCipher = Cipher.getInstance(ASYMMETRIC_ALGORITHM);
// extract digest
pkCipher.init(Cipher.DECRYPT_MODE, rsaPrivateKey);
byte[] encryptedElementSignature = Base64.decodeBase64(base64EncryptedElementSignature);
elementDigest = pkCipher.doFinal(encryptedElementSignature);
} catch (NoSuchAlgorithmException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException | NoSuchPaddingException e) {
String msg = "Error decrypting base64EncryptedElementSignature";
log.error(msg, e);
throw new CryptoException(msg + " Cause: " + e.toString());
}
// NOTE: will decrypt only the files in the media list, plus the encryptedSubmissionFile
File[] allFiles = instanceDir.listFiles();
List<File> filesToProcess = new ArrayList<>();
for (File f : allFiles) {
if (mediaNames.contains(f.getName())) {
filesToProcess.add(f);
} else if (encryptedSubmissionFile.equals(f.getName())) {
filesToProcess.add(f);
}
}
// should have all media files plus one submission.xml.enc file
if (filesToProcess.size() != mediaNames.size() + 1) {
// figure out what we're missing...
int lostFileCount = 0;
List<String> missing = new ArrayList<>();
for (String name : mediaNames) {
if (name == null) {
// this was lost due to an pre-ODK Aggregate 1.4.5 mark-as-complete action
++lostFileCount;
continue;
}
File f = new File(instanceDir, name);
if (!filesToProcess.contains(f)) {
missing.add(name);
}
}
StringBuilder b = new StringBuilder();
for (String name : missing) {
b.append(" ").append(name);
}
if (!filesToProcess.contains(new File(instanceDir, encryptedSubmissionFile))) {
b.append(" ").append(encryptedSubmissionFile);
throw new FileSystemException("Error decrypting: " + instanceDir.getName() + " Missing files:" + b.toString());
} else {
// ignore the fact that we don't have the lost files
if (filesToProcess.size() + lostFileCount != mediaNames.size() + 1) {
throw new FileSystemException("Error decrypting: " + instanceDir.getName() + " Missing files:" + b.toString());
}
}
}
// decrypt the media files IN ORDER.
for (String mediaName : mediaNames) {
String displayedName = (mediaName == null) ? "<missing .enc file>" : mediaName;
File f = (mediaName == null) ? null : new File(instanceDir, mediaName);
try {
decryptFile(ei, f, unencryptedDir);
} catch (InvalidKeyException | NoSuchPaddingException | InvalidAlgorithmParameterException | NoSuchAlgorithmException e) {
String msg = "Error decrypting:" + displayedName;
log.error(msg, e);
throw new CryptoException(msg + " Cause: " + e.toString());
} catch (IOException e) {
String msg = "Error decrypting:" + displayedName;
log.error(msg, e);
throw new FileSystemException(msg + " Cause: " + e.toString());
}
}
// decrypt the submission file
File f = new File(instanceDir, encryptedSubmissionFile);
try {
decryptFile(ei, f, unencryptedDir);
} catch (InvalidKeyException | NoSuchPaddingException | InvalidAlgorithmParameterException | NoSuchAlgorithmException e) {
log.error("Error decrypting file", e);
throw new CryptoException("Error decrypting:" + f.getName() + " Cause: " + e.toString());
} catch (IOException e) {
log.error("Error decrypting file", e);
throw new FileSystemException("Error decrypting:" + f.getName() + " Cause: " + e.toString());
}
// get the FIM for the decrypted submission file
File submissionFile = new File(unencryptedDir, encryptedSubmissionFile.substring(0, encryptedSubmissionFile.lastIndexOf(".enc")));
FormInstanceMetadata submissionFim;
try {
Document subDoc = XmlManipulationUtils.parseXml(submissionFile);
submissionFim = XmlManipulationUtils.getFormInstanceMetadata(subDoc.getRootElement());
} catch (ParsingException | FileSystemException e) {
log.error("Error decrypting submission", e);
throw new FileSystemException("Error decrypting: " + submissionFile.getName() + " Cause: " + e);
}
boolean same = submissionFim.xparam.formId.equals(fim.xparam.formId);
if (!same) {
throw new FileSystemException("Error decrypting:" + unencryptedDir.getName() + " Cause: form instance metadata differs from that in manifest");
}
// Construct the element signature string
StringBuilder b = new StringBuilder();
appendElementSignatureSource(b, fim.xparam.formId);
if (fim.xparam.modelVersion != null) {
appendElementSignatureSource(b, fim.xparam.modelVersion);
}
appendElementSignatureSource(b, base64EncryptedSymmetricKey);
appendElementSignatureSource(b, fim.instanceId);
boolean missingFile = false;
for (String encFilename : mediaNames) {
if (encFilename == null) {
missingFile = true;
continue;
}
File decryptedFile = new File(unencryptedDir, encFilename.substring(0, encFilename.lastIndexOf(".enc")));
if (decryptedFile.getName().endsWith(".missing")) {
// this is a missing file -- we will not be able to
// confirm the signature of the submission.
missingFile = true;
continue;
}
String md5 = FileSystemUtils.getMd5Hash(decryptedFile);
appendElementSignatureSource(b, decryptedFile.getName() + "::" + md5);
}
String md5 = FileSystemUtils.getMd5Hash(submissionFile);
appendElementSignatureSource(b, submissionFile.getName() + "::" + md5);
// compute the digest of the element signature string
byte[] messageDigest;
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(b.toString().getBytes("UTF-8"));
messageDigest = md.digest();
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
String msg = "Error computing xml signature";
log.error(msg, e);
throw new CryptoException(msg + " Cause: " + e);
}
same = true;
for (int i = 0; i < messageDigest.length; ++i) {
if (messageDigest[i] != elementDigest[i]) {
same = false;
break;
}
}
return same;
}
use of org.opendatakit.briefcase.model.ParsingException in project briefcase by opendatakit.
the class TransferFromODK method doAction.
@Override
public boolean doAction() {
boolean allSuccessful = true;
for (FormStatus fs : formsToTransfer) {
boolean isSuccessful = true;
try {
if (terminationFuture.isCancelled()) {
fs.setStatusString("Aborted. Skipping fetch of form and submissions...", true);
EventBus.publish(new FormStatusEvent(fs));
return false;
}
BriefcaseFormDefinition briefcaseLfd = doResolveOdkCollectFormDefinition(fs);
if (briefcaseLfd == null) {
allSuccessful = isSuccessful = false;
continue;
}
OdkCollectFormDefinition odkFormDef = (OdkCollectFormDefinition) fs.getFormDefinition();
File odkFormDefFile = odkFormDef.getFormDefinitionFile();
final String odkFormName = odkFormDefFile.getName().substring(0, odkFormDefFile.getName().lastIndexOf("."));
DatabaseUtils formDatabase = null;
try {
formDatabase = DatabaseUtils.newInstance(briefcaseLfd.getFormDirectory());
File destinationFormInstancesDir;
try {
destinationFormInstancesDir = FileSystemUtils.getFormInstancesDirectory(briefcaseLfd.getFormDirectory());
} catch (FileSystemException e) {
allSuccessful = isSuccessful = false;
String msg = "unable to create instances folder";
log.error(msg, e);
fs.setStatusString(msg + ": " + e.getMessage(), false);
EventBus.publish(new FormStatusEvent(fs));
continue;
}
// we have the needed directory structure created...
fs.setStatusString("preparing to retrieve instance data", true);
EventBus.publish(new FormStatusEvent(fs));
// construct up the list of folders that might have ODK form data.
File odkFormInstancesDir = new File(odkFormDefFile.getParentFile().getParentFile(), "instances");
// rely on ODK naming conventions to identify form data files...
File[] odkFormInstanceDirs = odkFormInstancesDir.listFiles(pathname -> {
boolean beginsWithFormName = pathname.getName().startsWith(odkFormName);
if (!beginsWithFormName)
return false;
// skip the separator character, as it varies between 1.1.5, 1.1.6 and 1.1.7
String afterName = pathname.getName().substring(odkFormName.length() + 1);
// aftername should be a reasonable date though we allow extra stuff at the end...
// protects against someone having "formname" and "formname_2"
// and us mistaking "formname_2_2009-01-02_15_10_03" as containing
// instance data for "formname" instead of "formname_2"
boolean outcome = afterName.matches("^[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}.*");
return outcome;
});
if (odkFormInstanceDirs != null) {
int instanceCount = 1;
for (File dir : odkFormInstanceDirs) {
if (terminationFuture.isCancelled()) {
allSuccessful = isSuccessful = false;
fs.setStatusString("aborting retrieving submissions...", true);
EventBus.publish(new FormStatusEvent(fs));
return false;
}
// 1.1.8 -- submission is saved as submission.xml.
// full instance data is stored as directoryName.xml (as is the convention in 1.1.5, 1.1.7)
String instanceId = null;
File fullXml = new File(dir, dir.getName() + ".xml");
File xml = new File(dir, "submission.xml");
if (!xml.exists() && fullXml.exists()) {
// e.g., 1.1.5, 1.1.7
xml = fullXml;
}
// rename it to match the directory name.
if (!xml.exists()) {
File[] xmlFiles = dir.listFiles(fileEndsWithXml);
if (xmlFiles.length == 1) {
try {
FileUtils.moveFile(xmlFiles[0], xml);
} catch (IOException e) {
allSuccessful = isSuccessful = false;
String msg = "unable to rename form instance xml";
log.error(msg, e);
fs.setStatusString(msg + ": " + e.getMessage(), false);
EventBus.publish(new FormStatusEvent(fs));
continue;
}
}
}
if (xml.exists()) {
// Check if the instance has an instanceID
try {
XmlManipulationUtils.FormInstanceMetadata formInstanceMetadata = XmlManipulationUtils.getFormInstanceMetadata(XmlManipulationUtils.parseXml(xml).getRootElement());
instanceId = formInstanceMetadata.instanceId;
} catch (ParsingException e) {
log.error("failed to get instance id from submission", e);
}
// OK, we can copy the directory off...
// Briefcase instances directory name is arbitrary.
// Rename the xml within that to always be "submission.xml"
// to remove the correspondence to the directory name.
File scratchInstance = FileSystemUtils.getFormSubmissionDirectory(destinationFormInstancesDir, dir.getName());
String safeName = scratchInstance.getName();
int i = 2;
boolean same = false;
while (scratchInstance.exists()) {
File[] contents = scratchInstance.listFiles(fileEndsWithXml);
if (contents == null || contents.length == 0)
break;
if (contents.length == 1) {
String itsInstanceId = null;
try {
XmlManipulationUtils.FormInstanceMetadata formInstanceMetadata = XmlManipulationUtils.getFormInstanceMetadata(XmlManipulationUtils.parseXml(contents[0]).getRootElement());
itsInstanceId = formInstanceMetadata.instanceId;
// if yes don't copy it, skip to next file
if (itsInstanceId != null && itsInstanceId.equals(instanceId) && FileSystemUtils.getMd5Hash(xml).equals(FileSystemUtils.getMd5Hash(contents[0]))) {
same = true;
break;
}
} catch (ParsingException e) {
log.error("failed to parse submission", e);
}
}
scratchInstance = new File(destinationFormInstancesDir, safeName + "-" + Integer.toString(i));
i++;
}
if (same) {
fs.setStatusString("already present - skipping: " + xml.getName(), true);
EventBus.publish(new FormStatusEvent(fs));
continue;
}
try {
FileUtils.copyDirectory(dir, scratchInstance);
} catch (IOException e) {
allSuccessful = isSuccessful = false;
String msg = "unable to copy saved instance";
log.error(msg, e);
fs.setStatusString(msg + ": " + e.getMessage(), false);
EventBus.publish(new FormStatusEvent(fs));
continue;
}
if (xml.equals(fullXml)) {
// need to rename
File odkSubmissionFile = new File(scratchInstance, fullXml.getName());
File scratchSubmissionFile = new File(scratchInstance, "submission.xml");
try {
FileUtils.moveFile(odkSubmissionFile, scratchSubmissionFile);
} catch (IOException e) {
allSuccessful = isSuccessful = false;
String msg = "unable to rename submission file to submission.xml";
log.error(msg, e);
fs.setStatusString(msg + ": " + e.getMessage(), false);
EventBus.publish(new FormStatusEvent(fs));
continue;
}
} else {
// delete the full xml file (keep only the submission.xml)
File odkSubmissionFile = new File(scratchInstance, fullXml.getName());
odkSubmissionFile.delete();
}
fs.setStatusString(String.format("retrieving (%1$d)", instanceCount), true);
EventBus.publish(new FormStatusEvent(fs));
++instanceCount;
}
}
}
} catch (SQLException | FileSystemException e) {
allSuccessful = isSuccessful = false;
String msg = "unable to open form database";
log.error(msg, e);
fs.setStatusString(msg + ": " + e.getMessage(), false);
EventBus.publish(new FormStatusEvent(fs));
continue;
} finally {
if (formDatabase != null) {
try {
formDatabase.close();
} catch (SQLException e) {
allSuccessful = isSuccessful = false;
String msg = "unable to close form database";
log.error(msg, e);
fs.setStatusString(msg + ": " + e.getMessage(), false);
EventBus.publish(new FormStatusEvent(fs));
continue;
}
}
}
} finally {
if (isSuccessful) {
fs.setStatusString(ServerFetcher.SUCCESS_STATUS, true);
EventBus.publish(new FormStatusEvent(fs));
} else {
fs.setStatusString(ServerFetcher.FAILED_STATUS, true);
EventBus.publish(new FormStatusEvent(fs));
}
}
}
return allSuccessful;
}
use of org.opendatakit.briefcase.model.ParsingException in project briefcase by opendatakit.
the class ServerFetcher method downloadSubmission.
private void downloadSubmission(File formInstancesDir, DatabaseUtils formDatabase, BriefcaseFormDefinition lfd, FormStatus fs, String uri) throws Exception {
File instanceFolder = formDatabase.hasRecordedInstance(uri);
if (instanceFolder != null) {
// check if the submission file is present in the folder before skipping
File instance = new File(instanceFolder, "submission.xml");
File instanceEncrypted = new File(instanceFolder, "submission.xml.enc");
if (instance.exists() || instanceEncrypted.exists()) {
log.info("already present - skipping fetch: " + uri);
return;
}
}
String formId = lfd.getSubmissionKey(uri);
if (isCancelled()) {
fs.setStatusString("aborting fetch of submission...", true);
EventBus.publish(new FormStatusEvent(fs));
throw new SubmissionDownloadException("Transfer cancelled by user.");
}
String baseUrl = serverInfo.getUrl() + "/view/downloadSubmission";
Map<String, String> params = new HashMap<>();
params.put("formId", formId);
String fullUrl = WebUtils.createLinkWithProperties(baseUrl, params);
AggregateUtils.DocumentFetchResult result;
try {
DocumentDescription submissionDescription = new DocumentDescription("Fetch of a submission failed. Detailed error: ", "Fetch of a submission failed.", "submission", terminationFuture);
result = AggregateUtils.getXmlDocument(fullUrl, serverInfo, false, submissionDescription, null);
} catch (XmlDocumentFetchException e) {
throw new SubmissionDownloadException(e.getMessage());
}
// and parse the document...
SubmissionManifest submissionManifest;
try {
submissionManifest = XmlManipulationUtils.parseDownloadSubmissionResponse(result.doc);
} catch (ParsingException e) {
throw new SubmissionDownloadException(e.getMessage());
}
String msg = "Fetched instanceID=" + submissionManifest.instanceID;
log.info(msg);
if (FileSystemUtils.hasFormSubmissionDirectory(formInstancesDir, submissionManifest.instanceID)) {
// create instance directory...
File instanceDir = FileSystemUtils.assertFormSubmissionDirectory(formInstancesDir, submissionManifest.instanceID);
// fetch attachments
for (MediaFile m : submissionManifest.attachmentList) {
downloadMediaFileIfChanged(instanceDir, m, fs);
}
// write submission file -- we rely on instanceId being unique...
File submissionFile = new File(instanceDir, "submission.xml");
OutputStreamWriter fo = new OutputStreamWriter(new FileOutputStream(submissionFile), "UTF-8");
fo.write(submissionManifest.submissionXml);
fo.close();
// if we get here, we know that this is a completed submission
// (because it was in /view/submissionList) and that we safely
// copied it into the storage area (because we didn't get any
// exceptions).
formDatabase.assertRecordedInstanceDirectory(uri, instanceDir);
} else {
// create instance directory...
File instanceDir = FileSystemUtils.assertFormSubmissionDirectory(formInstancesDir, submissionManifest.instanceID);
// fetch attachments
for (MediaFile m : submissionManifest.attachmentList) {
downloadMediaFileIfChanged(instanceDir, m, fs);
}
// write submission file
File submissionFile = new File(instanceDir, "submission.xml");
OutputStreamWriter fo = new OutputStreamWriter(new FileOutputStream(submissionFile), "UTF-8");
fo.write(submissionManifest.submissionXml);
fo.close();
// if we get here, we know that this is a completed submission
// (because it was in /view/submissionList) and that we safely
// copied it into the storage area (because we didn't get any
// exceptions).
formDatabase.assertRecordedInstanceDirectory(uri, instanceDir);
}
}
Aggregations