com.lionbridge.content.sdk.utilities.ZipUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of liox-content-sdk-java Show documentation
Show all versions of liox-content-sdk-java Show documentation
Client for Lionbridge Ondemand API
package com.lionbridge.content.sdk.utilities;
import com.lionbridge.content.sdk.ContentAPIException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
public class ZipUtils {
private final Logger LOGGER = LoggerFactory.getLogger(ZipUtils.class);
private String zipFilePath = null;
public String getZipFilePath() {
return this.zipFilePath;
}
public void setZipFilePath(final String pathIn) {
this.zipFilePath = pathIn;
}
/**
* Create a new ZipUtils instance and set the zip file path accordingly.
* @param pathIn Set the zip file path to this if it is set.
* @param strTranslationJobID The ID of the Translation JOB
*/
public ZipUtils(final String pathIn, final String strTranslationJobID) {
if (null != pathIn && !pathIn.trim().isEmpty()) {
this.setZipFilePath(pathIn);
}
if(null == this.zipFilePath) {
this.setZipFilePath(this.createZipFilePath("/tmp", strTranslationJobID, true, true));
}
}
/**
* Create a zip file path.
* @param rootFolder The folder in which to create the zip folder
* @param strTranslationJobID The job ID to parse (we only want the last part)
* @param includeDate flag to select whether to include the date in the path
* @param includeRandomizer flag to select whether to add a randomizer to the path
* @return the path in string form
*/
public String createZipFilePath(final String rootFolder,
final String strTranslationJobID, boolean includeDate, boolean includeRandomizer) {
String newZipFilePath;
// get the job ID name (trimming the path off of it)
String justJobName = "";
try {
final String[] jobIdParts = strTranslationJobID.split("/");
if(null != jobIdParts) {
// ensure there is at least one part from the split
if(0 < jobIdParts.length) {
justJobName = jobIdParts[jobIdParts.length - 1];
} else {
this.LOGGER.debug("JobID: split of {} returned no objects.", strTranslationJobID);
}
} else {
this.LOGGER.debug("JobID: split of {} returned null.", strTranslationJobID);
}
} catch (Exception e1) {
this.LOGGER.debug("JobID split exception", e1);
}
// if we couldn't parse the Job ID, just use this as a default.
// Force date and randomizer to be added.
if(justJobName.trim().isEmpty()) {
justJobName = "OnDemandFiles";
includeDate = true;
includeRandomizer = true;
}
// now get the current time to append to the job name
String curTimeString = "";
if(includeDate) {
final Date curTime = new Date();
curTimeString = "_" + (new SimpleDateFormat("yyyyMMddHHmmss")).format(curTime);
}
// now generate a random 6 digit number to append after that.
String randomizerString = "";
if(includeRandomizer) {
Random randomGenerator = new Random();
final int randomizer = randomGenerator.nextInt(1000000);
randomizerString = "_" + String.format("%06d", randomizer);
}
// now build the path. Should look something like /tmp/jobname_20160401152436_013579 if both options are set.
newZipFilePath = rootFolder + "/" + justJobName + curTimeString + randomizerString;
this.LOGGER.debug("addFileToZipFolder: Path created: {}", newZipFilePath);
return newZipFilePath;
}
/**
* Create a zip file with all of the contents from the path saved in this class.
* The file name will be (zipFilePath).(serviceId).zip. If serviceId is null
* or blank, it will be (zipFilePath).zip
* @param serviceId The ID of the service being used.
* @return The completed zip file
* @throws ContentAPIException An exception containing any API errors
*/
public File createZipFile(final String serviceId) throws ContentAPIException {
try {
// create the zip file and folder objects
String finalZipName = this.zipFilePath;
String finalZipPath = this.zipFilePath;
if (null != serviceId && !serviceId.trim().isEmpty()) {
finalZipName += "." + serviceId;
finalZipPath += "/" + serviceId;
}
File zipFile = new File(finalZipName + ".zip");
File zipFolder = new File(finalZipPath);
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
// list the files and loop through them
File[] folderList = zipFolder.listFiles();
if(null != folderList) {
StringBuilder dirContents = new StringBuilder();
for(File singleFile : folderList) {
dirContents.append("\n\t").append(singleFile.getName());
if(singleFile.isFile()) {
// create a zip entry for this file and start adding it
ZipEntry fileToZip = new ZipEntry(singleFile.getName());
zipOut.putNextEntry(fileToZip);
try {
// copy the file into the zip using a byte stream
final FileInputStream inputFileStream = new FileInputStream(singleFile);
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
int byteRead = inputFileStream.read();
while(0 <= byteRead) {
byteStream.write(byteRead);
byteRead = inputFileStream.read();
}
final byte[] fileData = byteStream.toByteArray();
this.LOGGER.debug("addFileToZipFolder: Read {} bytes from input file {}/{}" +
fileData.length, finalZipPath, singleFile.getName());
zipOut.write(fileData, 0, fileData.length);
// close the input stream and the zip entry to reset for any more files
inputFileStream.close();
zipOut.closeEntry();
} catch (Exception e1) {
this.LOGGER.error("Got exception adding data to zip. {}", e1.getMessage(), e1);
e1.printStackTrace();
}
}
}
this.LOGGER.trace("Directory list for {}: {}", this.zipFilePath, dirContents);
}
// for cleanup purposes, close the ZipOutputStream
zipOut.close();
return zipFile;
} catch (Exception e) {
this.LOGGER.error("createZipFile EXCEPTION", e);
e.printStackTrace();
throw new ContentAPIException(e);
}
}
/**
* Determine if the extension from an input file name matches one of the items
* in a list. Note that this can pick up some "inside" extensions, like
* filename.txt.save will match TXT or SAVE.
* @param fileName Name to parse
* @param extensions List of extensions to search for
* @return True if filename matches the extension. False if not.
*/
private boolean fileMatchesExtensions(final String fileName, final List extensions) {
if(fileName.contains(".")) {
String[] fileNameParts = fileName.split("\\.");
for(String fileNamePart : fileNameParts) {
this.LOGGER.trace("fileMatchesExtensions: part {}, extensions {}",
fileNamePart, extensions.toString());
if(extensions.contains(fileNamePart.trim().toUpperCase())) {
return true;
}
}
}
return false;
}
/**
* Move files into the applicable service ID subfolder
* @param serviceMap map containing file extensions by serviceID
*/
public void arrangeFilesByService(final HashMap> serviceMap) {
// Make sure the folder exists for the zip file
File zipFolder = new File(this.zipFilePath);
if(!zipFolder.exists()) {
zipFolder.mkdir();
}
// loop through all of the service IDs
for(String serviceId : serviceMap.keySet()) {
// create a subdirectory for each service ID
File serviceFolder = new File(this.zipFilePath + "/" + serviceId);
if(!serviceFolder.exists()) {
serviceFolder.mkdirs();
}
// find all of the files matching the extensions in the map for this service
// and move each file into this folder
File[] directoryList = zipFolder.listFiles();
if(null != directoryList) {
String dirContents = "";
for(File singleFile : directoryList) {
dirContents += "\n\t" + singleFile.getPath();
// get file extension and compare it to the map
if(singleFile.isFile()) {
if(this.fileMatchesExtensions(singleFile.getName(), serviceMap.get(serviceId))) {
dirContents += " (MOVED)";
File fileCopy = new File(this.zipFilePath + "/" + serviceId + "/" + singleFile.getName());
try {
Files.move(FileSystems.getDefault().getPath(singleFile.getPath()),
FileSystems.getDefault().getPath(fileCopy.getPath()),
StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
this.LOGGER.error("Got I/O Exception moving file {}",
singleFile.getName(), e);
}
} else {
this.LOGGER.debug("arrangeFilesByService: File name {}" +
" did not match extensions.", singleFile.getName());
}
}
}
this.LOGGER.debug("arrangeFilesByService: Directory list for {}: {}", this.zipFilePath, dirContents);
} else {
this.LOGGER.debug("arrangeFilesByService: Directory list for {} is null.", this.zipFilePath);
}
}
}
/**
* Add a specified file to the zip folder for an input job ID. The files
* will be zipped up in a separate process.
* @param inputFile the file to add to the zip folder
* @throws ContentAPIException An exception containing any API errors
*/
public void addFileToZipFolder(File inputFile) throws ContentAPIException {
try {
// Make sure the folder exists for the zip file
File zipFolder = new File(this.zipFilePath);
if(!zipFolder.exists()) {
zipFolder.mkdir();
}
// Copy the file into the zip folder
File fileCopy = new File(this.zipFilePath + "/" + inputFile.getName());
Files.copy(FileSystems.getDefault().getPath(inputFile.getPath()),
FileSystems.getDefault().getPath(fileCopy.getPath()),
StandardCopyOption.REPLACE_EXISTING);
} catch (Exception e) {
this.LOGGER.error("addFileToZipFolder EXCEPTION: ", e);
throw new ContentAPIException(e);
}
}
/**
* Extract all of the files from the specified zip file into an extract folder
* @param zipFile Zip file to process
* @param extractDir subdirectory to extract to - will create a subdirectory
* with this name in the same folder as the input zip file
* @return The path of the extracted file
*/
public static String extractFilesFromZip(final File zipFile, final String extractDir) {
try {
ZipInputStream zipIn = new ZipInputStream(new FileInputStream(zipFile.getPath()));
ZipEntry entry = zipIn.getNextEntry();
final String folderPath = zipFile.getParent() + File.separator + extractDir;
final File extractFolder = new File(folderPath);
if(!extractFolder.exists()) {
extractFolder.mkdirs();
}
// iterates over entries in the zip file
while (null != entry) {
if (!entry.isDirectory()) {
// if the entry is a file, extracts it
final String filePath = folderPath + File.separator + entry.getName();
extractFile(filePath);
}
zipIn.closeEntry();
entry = zipIn.getNextEntry();
}
zipIn.close();
return folderPath;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
private static void extractFile(String filePath) throws IOException {
File zipSubfile = new File(filePath);
File zipSubfileSubfolder = new File(zipSubfile.getParent());
if(!zipSubfileSubfolder.exists()) {
zipSubfileSubfolder.mkdirs();
}
FileOutputStream fileStream = new FileOutputStream(zipSubfile);
fileStream.close();
}
private class ZipFolderVisitor extends SimpleFileVisitor {
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
ZipUtils.this.LOGGER.debug("postVisitDirectory: Deleting directory {}", dir.toString());
try {
Files.delete(dir);
} catch (IOException e) {
ZipUtils.this.LOGGER.error("postVisitDirectory: EXCEPTION deleting directory {}",
dir.toString(), e);
throw e;
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
ZipUtils.this.LOGGER.debug("visitFile: Deleting file {}", file.toString());
try {
Files.delete(file);
} catch (IOException e) {
ZipUtils.this.LOGGER.error("visitFile: EXCEPTION deleting file {}",
file.toString(), e);
throw e;
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
return FileVisitResult.CONTINUE;
}
}
/**
* Delete the directory created at the path specified in zipFilePath.
* Then delete the zip file if specified by the caller.
* @param deleteZip if set to true, delete the zip file with the same name.
*/
public void cleanUpZipFileAndFolder(final boolean deleteZip) {
File zipFolder = new File(this.zipFilePath);
// print the contents of the folder that was already zipped
File[] directoryList = zipFolder.listFiles();
if(null != directoryList) {
for(File singleFile : directoryList) {
try {
if(singleFile.isFile()) {
this.LOGGER.debug("cleanUpZipFileAndFolder Deleting file {}", singleFile.getPath());
singleFile.delete();
} else {
this.LOGGER.debug("cleanUpZipFileAndFolder object {} is not a file.",
singleFile.getPath());
}
} catch (Exception e) {
this.LOGGER.error("cleanUpZipFileAndFolder file delete EXCEPTION", e);
}
}
}
directoryList = zipFolder.listFiles();
if (null != directoryList && 0 < directoryList.length) {
try {
Files.walkFileTree(zipFolder.toPath(), new ZipFolderVisitor());
} catch (IOException e1) {
this.LOGGER.error("cleanUpZipFileAndFolder walk file tree EXCEPTION", e1);
}
}
// double check the directory to ensure it's empty (so we can delete it too)
if(zipFolder.exists()) {
File[] directoryListAfter = zipFolder.listFiles();
boolean directoryEmpty = true;
if(null != directoryListAfter) {
for(File singleFile : directoryListAfter) {
if(singleFile.isFile() || singleFile.isDirectory()) {
directoryEmpty = false;
break;
}
}
}
if(directoryEmpty) {
try {
zipFolder.delete();
} catch (Exception e) {
this.LOGGER.error("cleanUpZipFileAndFolder folder delete EXCEPTION", e);
}
}
}
if(deleteZip) {
this.LOGGER.debug("Will delete file " + this.zipFilePath + ".zip.");
try {
File zipFile = new File(this.zipFilePath + ".zip");
zipFile.delete();
} catch (Exception e) {
this.LOGGER.error("cleanUpZipFileAndFolder Zip delete EXCEPTION", e);
}
}
}
}