/*******************************************************************************
* Open Behavioral Health Information Technology Architecture (OBHITA.org)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
package gov.samhsa.acs.common.xdm;
import gov.samhsa.acs.common.exception.DS4PException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
/**
* The Class XdmZipUtils.
*/
public class XdmZipUtils {
/** The Constant XDM_SUB_FOLDER. */
private static final String XDM_SUB_FOLDER = "SUBSET01/";
/** The Constant PATH_INDEX. */
public static final String PATH_INDEX = "INDEX.html";
/** The Constant PATH_README. */
public static final String PATH_README = "README.txt";
/** The Constant PATH_METADATA. */
public static final String PATH_METADATA = XDM_SUB_FOLDER + "METADATA.xml";
/** The Constant PATH_C32. */
public static final String PATH_C32 = XDM_SUB_FOLDER + "DOCUMENT.xml";
/** The Constant PATH_KEKENCRYPT. */
public static final String PATH_KEKENCRYPT = "kekEncryptionKey";
/** The Constant PATH_KEKMASKING. */
public static final String PATH_KEKMASKING = "kekMaskingKey";
/** The Constant PATH_XSL. */
public static final String PATH_XSL = XDM_SUB_FOLDER + "CDA.xsl";
/**
* Creates the xdm package.
*
* @param metadata the metadata
* @param xsl the xsl
* @param c32 the c32
* @param index the index
* @param readMe the read me
* @param kekMaskingKey the kek masking key (nillable)
* @param kekEncryptionKey the kek encryption key (nillable)
* @return the byte[]
*/
public static byte[] createXDMPackage(String metadata, String xsl, String c32,
String index, String readMe, byte[] kekMaskingKey,
byte[] kekEncryptionKey) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(os);
byte[] bytesOut = null;
byte[] c32Bytes = getUtfCustomBytes(c32);
byte[] metaBytes = getUtfCustomBytes(metadata);
byte[] xslBytes = getUtfCustomBytes(xsl);
byte[] indexBytes = getUtfCustomBytes(index);
byte[] readMeBytes = getUtfCustomBytes(readMe);
try {
addZipEntry(PATH_C32, c32Bytes, zos);
addZipEntry(PATH_README, readMeBytes, zos);
addZipEntry(PATH_INDEX, indexBytes, zos);
addZipEntry(PATH_XSL, xslBytes, zos);
addZipEntry(PATH_METADATA, metaBytes, zos);
if(kekEncryptionKey != null){
addZipEntry(PATH_KEKENCRYPT, kekEncryptionKey, zos);
}
if(kekMaskingKey != null){
addZipEntry(PATH_KEKMASKING, kekMaskingKey, zos);
}
zos.finish();
bytesOut = os.toByteArray();
}
catch (IOException e) {
throw new DS4PException(e.toString(), e);
}
finally {
try {
zos.flush();
zos.close();
os.flush();
os.close();
}
catch (IOException e) {
// do nothing here
}
}
return bytesOut;
}
/**
* Gets the utf custom bytes.
*
* @param str the str
* @return the utf custom bytes
*/
public static byte[] getUtfCustomBytes(String str) {
byte[] b = new byte[str.length()];
for (int i = 0; i < str.length(); i++) {
char strChar = str.charAt(i);
int bpos = i;
b[bpos] = (byte) (strChar & 0x00FF);
}
return b;
}
/**
* Adds the zip entry.
*
* @param pathName the path name
* @param contents the contents
* @param zos the zos
* @throws IOException Signals that an I/O exception has occurred.
*/
public static void addZipEntry(String pathName, byte[] contents, ZipOutputStream zos)
throws IOException {
ZipEntry entry = new ZipEntry(pathName);
entry.setSize(contents.length);
zos.putNextEntry(entry);
zos.write(contents);
zos.closeEntry();
}
/**
* Gets the entry bytes.
*
* @param zipFileBytes the zip file bytes
* @param entryName the entry name
* @param entrySize the entry size
* @return the entry bytes
* @throws IOException Signals that an I/O exception has occurred.
*/
public static byte[] getEntryBytes(byte[] zipFileBytes,
String entryName, int entrySize) throws IOException {
ByteArrayInputStream file = new ByteArrayInputStream(zipFileBytes);
ZipInputStream zip_inputstream = new ZipInputStream(file);
ZipEntry current_zip_entry = null;
byte[] buf = new byte[entrySize];
boolean found = false;
current_zip_entry = zip_inputstream.getNextEntry();
while ((current_zip_entry != null) && !found) {
if (current_zip_entry.getName().equals(entryName)) {
found = true;
ByteArrayOutputStream output = getByteArrayOutputStream(zip_inputstream);
buf = output.toByteArray();
output.flush();
output.close();
} else {
current_zip_entry = zip_inputstream.getNextEntry();
}
}
zip_inputstream.close();
file.close();
return buf;
}
/**
* Gets the byte array output stream.
*
* @param zipInputstream the zip inputstream
* @return the byte array output stream
* @throws IOException Signals that an I/O exception has occurred.
*/
public static ByteArrayOutputStream getByteArrayOutputStream(
ZipInputStream zipInputstream) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
int data = 0;
while ((data = zipInputstream.read()) != -1) {
output.write(data);
}
return output;
}
/**
* Write zipfile.
*
* @param zipPath the zip path
* @param bytes the bytes
* @throws IOException Signals that an I/O exception has occurred.
*/
public static void writeZipfile(String zipPath, byte[] bytes) throws IOException {
FileOutputStream zipos = new FileOutputStream(zipPath);
ZipOutputStream zout = new ZipOutputStream(zipos);
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ZipInputStream zipis = new ZipInputStream(bis);
ZipEntry current_zip_entry = null;
boolean found = false;
current_zip_entry = zipis.getNextEntry();
while ((current_zip_entry != null) && !found) {
zout.putNextEntry(current_zip_entry);
byte[] buf = new byte[4096];
int bytesRead = 0;
while ((bytesRead = zipis.read(buf)) != -1) {
zout.write(buf, 0, bytesRead);
}
current_zip_entry = zipis.getNextEntry();
}
bis.close();
zout.close();
}
}