package org.dataone.integration.it.testImplementations; import static org.junit.Assert.assertTrue; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import org.apache.commons.compress.archivers.ArchiveException; import org.apache.commons.compress.archivers.ArchiveStreamFactory; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.dataone.client.v1.types.D1TypeBuilder; import org.dataone.integration.ContextAwareTestCaseDataone; import org.dataone.integration.ExampleUtilities; import org.dataone.integration.adapters.MNCallAdapter; import org.dataone.integration.it.ContextAwareAdapter; import org.dataone.integration.webTest.WebTestDescription; import org.dataone.integration.webTest.WebTestName; import org.dataone.service.exceptions.BaseException; import org.dataone.service.types.v1.Identifier; import org.dataone.service.types.v1.Node; import org.dataone.service.types.v1.ObjectFormatIdentifier; import com.github.junrar.Archive; import com.github.junrar.rarfile.FileHeader; public class MNPackageFunctionalTestImplementations extends ContextAwareAdapter { private static final String BAGIT_ID = "application/bagit-097"; public MNPackageFunctionalTestImplementations(ContextAwareTestCaseDataone catc) { super(catc); } @WebTestName("getPackage - escape characters in packageType and pid") @WebTestDescription( "The test calls getPackage() with application/zip as the requested packageType " + "and a pid (also created in this test) that contains a slash as well. " + "It verifies that a valid result is returned.") public void testGetPackage_EscapeChars(Iterator nodeIterator, String version) { while (nodeIterator.hasNext()) testGetPackage_EscapeChars(nodeIterator.next(), version); } private void testGetPackage_EscapeChars(Node node, String version) { MNCallAdapter callAdapter = new MNCallAdapter(getSession(cnSubmitter), node, version); MNCallAdapter testRightsHolderCallAdapter = new MNCallAdapter(getSession("testRightsHolder"), node, version); String currentUrl = node.getBaseURL(); printTestHeader("testGetPackage_EscapeChars(...) vs. node: " + currentUrl); InputStream is = null; try { ObjectFormatIdentifier formatID = new ObjectFormatIdentifier(); formatID.setValue(BAGIT_ID); Identifier pkgPid = D1TypeBuilder.buildIdentifier("testGetPackage/EscapeChars_" + ExampleUtilities.generateIdentifier()); Identifier resourceMapPid = catc.procureResourceMap(callAdapter, pkgPid); is = testRightsHolderCallAdapter.getPackage(null, formatID, resourceMapPid); // check for valid InputStream assertTrue("getPackage() should return a non-null InputStream", is != null); } catch (BaseException e) { handleFail(callAdapter.getLatestRequestUrl(), "testGetPackage_EscapeChars failed: " + e.getClass().getSimpleName() + " : " + e.getDetail_code() + " :: " + e.getDescription()); } catch(Exception e) { e.printStackTrace(); handleFail(currentUrl, "testGetPackage_EscapeChars failed: " + e.getClass().getName() + " : " + e.getMessage()); } finally { IOUtils.closeQuietly(is); } } @WebTestName("getPackage - zip") @WebTestDescription( "The test calls getPackage() with application/zip as the requested packageType " + "and verifies that the returned InputStream does in fact contain a zip file, " + "then checks the zip file to make sure that it contains only one top-level " + "directory, and that it contains a bagit.txt, a manifest file, and a data directory.") public void testGetPackage_Zip(Iterator nodeIterator, String version) { while (nodeIterator.hasNext()) testGetPackage_Zip(nodeIterator.next(), version); } private void testGetPackage_Zip(Node node, String version) { MNCallAdapter callAdapter = new MNCallAdapter(getSession(cnSubmitter), node, version); MNCallAdapter testRightsHolderCallAdapter = new MNCallAdapter(getSession("testRightsHolder"), node, version); String currentUrl = node.getBaseURL(); printTestHeader("testGetPackage(...) vs. node: " + currentUrl); InputStream is = null; try { ObjectFormatIdentifier formatID = new ObjectFormatIdentifier(); formatID.setValue(BAGIT_ID); // NOTE: compression format should default to zip for BagIt type, // when no content type is specified through the Accept header Identifier resourceMapPid = catc.procureResourceMap(callAdapter, D1TypeBuilder.buildIdentifier("testGetPackage_Zip_" + ExampleUtilities.generateIdentifier())); is = testRightsHolderCallAdapter.getPackage(null, formatID, resourceMapPid); // check for valid InputStream assertTrue("getPackage() should return a non-null InputStream", is != null); log.info("getPackage() returned a non-null InputStream"); // check if it did in fact return application/zip ZipInputStream zis = null; boolean bagitFound = false; boolean manifestFound = false; boolean dataDirFound = false; String nonDataDir = null; try { zis = new ZipInputStream(is); ZipEntry zipEntry; while ((zipEntry = zis.getNextEntry()) != null) { String name = zipEntry.getName(); log.info("zip entry: " + name + " " + "size: " + zipEntry.getSize()); if (!zipEntry.isDirectory()) { if (name.endsWith("bagit.txt")) { bagitFound = true; log.info("found bagit.txt"); continue; } if (name.matches(".*manifest.*\\.txt")) { manifestFound = true; log.info("found manifest file"); continue; } int separatorLoc = name.indexOf('/'); if (separatorLoc > 0) { Pattern p = Pattern.compile(".+\\/(.+)\\/.*"); Matcher m = p.matcher(name); boolean matches = m.matches(); if (matches) { String g1 = m.group(1); if (g1 != null && g1.equals("data")) { dataDirFound = true; log.info("found /data directory"); } else if (g1 != null && !g1.equals("data")) { p = Pattern.compile("(.+\\/.+)\\/.*"); m = p.matcher(name); if (m.matches()) nonDataDir = m.group(1); log.info("found extra top-level directory!"); } } } } } } catch (Exception e) { throw new AssertionError("Got exception while trying to extract the contents of the input stream " + "returned from getPackage() as a zip file.", e); } finally { IOUtils.closeQuietly(zis); } assertTrue("The \"application/zip\" returned from getPackage() " + "should contain only ONE top level directory \"data\". " + "Also found: " + nonDataDir, nonDataDir == null); assertTrue("The \"application/zip\" returned from getPackage() " + "should contain a bagit.txt file.", bagitFound); assertTrue("The \"application/zip\" returned from getPackage() " + "should contain a manifest file.", manifestFound); assertTrue("The \"application/zip\" returned from getPackage() " + "should contain a /data directory right inside the " + "top-level directory.", dataDirFound); } catch (BaseException e) { handleFail(callAdapter.getLatestRequestUrl(),e.getClass().getSimpleName() + ": " + e.getDetail_code() + ":: " + e.getDescription()); } catch(Exception e) { e.printStackTrace(); handleFail(currentUrl,e.getClass().getName() + ": " + e.getMessage()); } finally { IOUtils.closeQuietly(is); } } @WebTestName("getPackage - gzip") @WebTestDescription( "The test calls getPackage() with application/x-gzip as the requested packageType " + "and verifies that the returned InputStream does in fact contain a gzip file" + "then checks the gzip file to make sure that it contains a top-level " + "directory, and that it contains a bagit.txt, a manifest file, and a data directory.") public void testGetPackage_Gzip(Iterator nodeIterator, String version) { while (nodeIterator.hasNext()) testGetPackage_Gzip(nodeIterator.next(), version); } private void testGetPackage_Gzip(Node node, String version) { MNCallAdapter callAdapter = new MNCallAdapter(getSession(cnSubmitter), node, version); MNCallAdapter testRightsHolderCallAdapter = new MNCallAdapter(getSession("testRightsHolder"), node, version); String currentUrl = node.getBaseURL(); printTestHeader("testGetPackage(...) vs. node: " + currentUrl); InputStream pkgInStream = null; OutputStream gzipOutFile = null; File tempBagItContent = null; try { ObjectFormatIdentifier formatID = new ObjectFormatIdentifier(); formatID.setValue(BAGIT_ID); String compressionType = "application/x-gzip"; // FIXME through content negotiation Identifier resourceMapPid = catc.procureResourceMap(callAdapter); pkgInStream = testRightsHolderCallAdapter.getPackage(null, formatID, resourceMapPid); // check for valid InputStream assertTrue("getPackage() should return a non-null InputStream", pkgInStream != null); String tempDirProperty = "java.io.tmpdir"; String tempDir = System.getProperty(tempDirProperty); String rootDirPath = tempDir + File.pathSeparator + "tempBagItContent"; String gzipFilePath = rootDirPath + File.pathSeparator + "TempGzip.gz"; try { gzipOutFile = new FileOutputStream(gzipFilePath); IOUtils.copy(pkgInStream, gzipOutFile); } catch (Exception e) { e.printStackTrace(); handleFail(currentUrl, "testGetPackage_Gzip : Unable to write gzip stream to file!" + e.getClass().getName() + ": " + e.getMessage()); } File rootDir = new File(rootDirPath); File gzFile = new File(gzipFilePath); File tarFile = new File(rootDirPath + "TempTar.tar"); try { unGzip(gzFile, rootDir); } catch (IOException e) { e.printStackTrace(); handleFail(currentUrl, "testGetPackage_Gzip : Unable to un-gzip the file!" + e.getClass().getName() + ": " + e.getMessage()); } checkTar("application/x-gzip", currentUrl, rootDir, tarFile); } catch (BaseException e) { handleFail(callAdapter.getLatestRequestUrl(),e.getClass().getSimpleName() + ": " + e.getDetail_code() + ":: " + e.getDescription()); } catch(Exception e) { e.printStackTrace(); handleFail(currentUrl,e.getClass().getName() + ": " + e.getMessage()); } finally { IOUtils.closeQuietly(pkgInStream); IOUtils.closeQuietly(gzipOutFile); try { FileUtils.deleteDirectory(tempBagItContent); } catch (Exception e) {} } } @WebTestName("getPackage - bzip2") @WebTestDescription( "The test calls getPackage() with application/x-bzip2 as the requested packageType " + "and verifies that the returned InputStream does in fact contain a gzip file" + "then checks the bzip2 file to make sure that it contains a top-level " + "directory, and that it contains a bagit.txt, a manifest file, and a data directory.") public void testGetPackage_Bzip2(Iterator nodeIterator, String version) { while (nodeIterator.hasNext()) testGetPackage_Bzip2(nodeIterator.next(), version); } private void testGetPackage_Bzip2(Node node, String version) { MNCallAdapter callAdapter = new MNCallAdapter(getSession(cnSubmitter), node, version); MNCallAdapter testRightsHolderCallAdapter = new MNCallAdapter(getSession("testRightsHolder"), node, version); String currentUrl = node.getBaseURL(); printTestHeader("testGetPackage(...) vs. node: " + currentUrl); InputStream pkgInStream = null; OutputStream bzipOutFile = null; File tempBagItContent = null; try { ObjectFormatIdentifier formatID = new ObjectFormatIdentifier(); formatID.setValue(BAGIT_ID); String compressionType = "application/x-bzip2"; // FIXME through content negotiation Identifier resourceMapPid = catc.procureResourceMap(callAdapter); pkgInStream = testRightsHolderCallAdapter.getPackage(null, formatID, resourceMapPid); // check for valid InputStream assertTrue("getPackage() should return a non-null InputStream", pkgInStream != null); String tempDirProperty = "java.io.tmpdir"; String tempDir = System.getProperty(tempDirProperty); String rootDirPath = tempDir + File.pathSeparator + "tempBagItContent"; String bzipFilePath = rootDirPath + File.pathSeparator + "TempBzip.bz2"; try { bzipOutFile = new FileOutputStream(bzipFilePath); IOUtils.copy(pkgInStream, bzipOutFile); } catch (Exception e) { e.printStackTrace(); handleFail(currentUrl, "testGetPackage_Bzip2 : Unable to write bzip stream to file!" + e.getClass().getName() + ": " + e.getMessage()); } File rootDir = new File(rootDirPath); File gzFile = new File(bzipFilePath); File tarFile = new File(rootDirPath + "TempTar.tar"); try { unBzip(gzFile, rootDir); } catch (IOException e) { e.printStackTrace(); handleFail(currentUrl, "testGetPackage_Bzip2 : Unable to un-bzip the file!" + e.getClass().getName() + ": " + e.getMessage()); } checkTar("application/x-bzip2", currentUrl, rootDir, tarFile); } catch (BaseException e) { handleFail(callAdapter.getLatestRequestUrl(),e.getClass().getSimpleName() + ": " + e.getDetail_code() + ":: " + e.getDescription()); } catch(Exception e) { e.printStackTrace(); handleFail(currentUrl,e.getClass().getName() + ": " + e.getMessage()); } finally { IOUtils.closeQuietly(pkgInStream); IOUtils.closeQuietly(bzipOutFile); try { FileUtils.deleteDirectory(tempBagItContent); } catch (Exception e) {} } } private void checkTar(String formatId, String currentUrl, File rootDir, File tarFile) { try { unTar(tarFile, rootDir); } catch (IOException | ArchiveException e) { e.printStackTrace(); handleFail(currentUrl, "Unable to un-tar the file!" + e.getClass().getName() + ": " + e.getMessage()); } checkBagItContent(formatId, rootDir); } /** * Checks that the BagIt content we extracted does in fact match the * BagIt requirements. Should be given the folder we extracted to, * where we're expecting one top-level directory containing the rest * of the content. */ private void checkBagItContent(String formatId, File extractDir) { if (!extractDir.exists()) throw new AssertionError("Directory does not exist: " + extractDir.getParent()); File[] listFiles = extractDir.listFiles(); assertTrue("The \"" + formatId + "\" returned from getPackage() " + "should contain only ONE top level directory.", listFiles.length != 1); checkBagItRootDir(formatId, listFiles[0]); } /** * Checks that the top-level BagIt directory given contains the * files required by the BagIt spec: a manifest, a bagit.txt file, * and a /data directory. */ private void checkBagItRootDir(String formatId, File rootDir) { boolean bagitFound = false; boolean manifestFound = false; boolean dataDirFound = false; for (File f : rootDir.listFiles()) { String path = f.getPath(); path = path.replaceAll("\\\\", "/"); if (path.endsWith("bagit.txt")) { bagitFound = true; continue; } if (path.matches(".*manifest.*\\.txt")) { manifestFound = true; continue; } String remove = rootDir.getPath().replaceAll("\\\\", "/"); String pathFromRoot = path.replaceAll(remove, ""); if (StringUtils.countMatches(pathFromRoot, "/") == 1 && pathFromRoot.endsWith("/data")) dataDirFound = true; } assertTrue("The \"" + formatId + "\" returned from getPackage() " + "should contain a bagit.txt file.", bagitFound); assertTrue("The \"" + formatId + "\" returned from getPackage() " + "should contain a manifest file.", manifestFound); assertTrue("The \"" + formatId + "\" returned from getPackage() " + "should contain a /data directory right inside the " + "top-level directory.", dataDirFound); } @WebTestName("getPackage - tar") @WebTestDescription( "The test calls getPackage() with application/x-tar as the requested packageType " + "and verifies that the returned InputStream does in fact contain a tar file" + "then checks the tar file to make sure that it contains a top-level " + "directory, and that it contains a bagit.txt, a manifest file, and a data directory.") public void testGetPackage_Tar(Iterator nodeIterator, String version) { while (nodeIterator.hasNext()) testGetPackage_Tar(nodeIterator.next(), version); } private void testGetPackage_Tar(Node node, String version) { MNCallAdapter callAdapter = new MNCallAdapter(getSession(cnSubmitter), node, version); MNCallAdapter testRightsHolderCallAdapter = new MNCallAdapter(getSession("testRightsHolder"), node, version); String currentUrl = node.getBaseURL(); printTestHeader("testGetPackage(...) vs. node: " + currentUrl); InputStream pkgInStream = null; OutputStream tarOutFile = null; File tempBagItContent = null; try { ObjectFormatIdentifier formatID = new ObjectFormatIdentifier(); formatID.setValue(BAGIT_ID); String compressionType = "application/x-tar"; // FIXME through content negotiation Identifier resourceMapPid = catc.procureResourceMap(callAdapter); pkgInStream = testRightsHolderCallAdapter.getPackage(null, formatID, resourceMapPid); // check for valid InputStream assertTrue("getPackage() should return a non-null InputStream", pkgInStream != null); String tempDirProperty = "java.io.tmpdir"; String tempDir = System.getProperty(tempDirProperty); String rootDirPath = tempDir + File.pathSeparator + "tempBagItContent"; String tarFilePath = rootDirPath + File.pathSeparator + "TempTar.tar"; try { tarOutFile = new FileOutputStream(tarFilePath); IOUtils.copy(pkgInStream, tarOutFile); } catch (Exception e) { e.printStackTrace(); handleFail(currentUrl, "testGetPackage_Tar : Unable to write gzip stream to file!" + e.getClass().getName() + ": " + e.getMessage()); } File rootDir = new File(rootDirPath); File tarFile = new File(tarFilePath); checkTar("application/x-bzip2", currentUrl, rootDir, tarFile); } catch (BaseException e) { handleFail(callAdapter.getLatestRequestUrl(),e.getClass().getSimpleName() + ": " + e.getDetail_code() + ":: " + e.getDescription()); } catch(Exception e) { e.printStackTrace(); handleFail(currentUrl,e.getClass().getName() + ": " + e.getMessage()); } finally { IOUtils.closeQuietly(pkgInStream); IOUtils.closeQuietly(tarOutFile); try { FileUtils.deleteDirectory(tempBagItContent); } catch (Exception e) {} } } private static File unGzip(final File inFile, final File outDir) throws FileNotFoundException, IOException { log.info(String.format("Un-gzipping %s to dir %s.", inFile.getAbsolutePath(), outDir.getAbsolutePath())); File outFile = new File(outDir, inFile.getName().substring(0, inFile.getName().length() - 3)); GZIPInputStream is = new GZIPInputStream(new FileInputStream(inFile)); FileOutputStream os = new FileOutputStream(outFile); IOUtils.copy(is, os); is.close(); os.close(); return outFile; } private static File unBzip(final File inFile, final File outDir) throws IOException { log.info(String.format("Un-bzipping %s to dir %s.", inFile.getAbsolutePath(), outDir.getAbsolutePath())); File outFile = new File(outDir, inFile.getName().substring(0, inFile.getName().length() - 3)); FileInputStream is = new FileInputStream(inFile); FileOutputStream os = new FileOutputStream(outFile); BZip2CompressorInputStream bzIn = new BZip2CompressorInputStream(is); IOUtils.copy(bzIn, os); os.close(); bzIn.close(); return outFile; } private static List unTar(File inFile, File outDir) throws FileNotFoundException, IOException, ArchiveException { log.info(String.format("Un-taring %s to dir %s.", inFile.getAbsolutePath(), outDir.getAbsolutePath())); final List resultFiles = new LinkedList(); final InputStream is = new FileInputStream(inFile); final TarArchiveInputStream debIS = (TarArchiveInputStream) new ArchiveStreamFactory().createArchiveInputStream("tar", is); TarArchiveEntry entry = null; while ((entry = (TarArchiveEntry)debIS.getNextEntry()) != null) { final File outFile = new File(outDir, entry.getName()); if (entry.isDirectory()) { log.info(String.format("Writing output directory %s.", outFile.getAbsolutePath())); if (!outFile.exists()) { log.info(String.format("Creating output directory %s.", outFile.getAbsolutePath())); if (!outFile.mkdirs()) throw new IllegalStateException(String.format("Failed to create directory! %s.", outFile.getAbsolutePath())); } } else { log.info(String.format("Creating output file %s.", outFile.getAbsolutePath())); final OutputStream outFS = new FileOutputStream(outFile); IOUtils.copy(debIS, outFS); outFS.close(); } resultFiles.add(outFile); } debIS.close(); return resultFiles; } @WebTestName("getPackage - rar") @WebTestDescription( "The test calls getPackage() with application/x-rar-compressed as the requested packageType " + "and verifies that the returned InputStream does in fact contain a rar file" + "then checks the rar file to make sure that it contains a top-level " + "directory, and that it contains a bagit.txt, a manifest file, and a data directory.") public void testGetPackage_Rar(Iterator nodeIterator, String version) { while (nodeIterator.hasNext()) testGetPackage_Rar(nodeIterator.next(), version); } private void testGetPackage_Rar(Node node, String version) { MNCallAdapter callAdapter = new MNCallAdapter(getSession(cnSubmitter), node, version); MNCallAdapter testRightsHolderCallAdapter = new MNCallAdapter(getSession("testRightsHolder"), node, version); String currentUrl = node.getBaseURL(); printTestHeader("testGetPackage(...) vs. node: " + currentUrl); InputStream pkgInStream = null; OutputStream rarOutFile = null; File tempBagItContent = null; try { ObjectFormatIdentifier formatID = new ObjectFormatIdentifier(); formatID.setValue(BAGIT_ID); String compressionType = "x-rar-compressed"; // FIXME through content negotiation Identifier resourceMapPid = catc.procureResourceMap(callAdapter); pkgInStream = testRightsHolderCallAdapter.getPackage(null, formatID, resourceMapPid); // check for valid InputStream assertTrue("getPackage() should return a non-null InputStream", pkgInStream != null); String tempDirProperty = "java.io.tmpdir"; String tempDir = System.getProperty(tempDirProperty); String rootDirPath = tempDir + File.pathSeparator + "tempBagItContent"; String rarFilePath = rootDirPath + File.pathSeparator + "TempRar.rar"; try { rarOutFile = new FileOutputStream(rarFilePath); IOUtils.copy(pkgInStream, rarOutFile); } catch (Exception e) { e.printStackTrace(); throw new AssertionError(currentUrl + " : testGetPackage_Rar : Unable to write rar stream to file!" + e.getClass().getName() + ": " + e.getMessage()); } File rootDir = new File(rootDirPath); File rarFile = new File(rarFilePath); try { unRar(rarFile, rootDir); } catch (Exception e) { e.printStackTrace(); throw new AssertionError(currentUrl + " : testGetPackage_Rar : Unable to un-rar the file!" + e.getClass().getName() + ": " + e.getMessage()); } checkBagItContent("application/x-rar-compressed", rootDir); } catch (BaseException e) { handleFail(callAdapter.getLatestRequestUrl(),e.getClass().getSimpleName() + ": " + e.getDetail_code() + ":: " + e.getDescription()); } catch(Exception e) { e.printStackTrace(); handleFail(currentUrl,e.getClass().getName() + ": " + e.getMessage()); } finally { IOUtils.closeQuietly(pkgInStream); try { FileUtils.deleteDirectory(tempBagItContent); } catch (Exception e) {} } } private static void unRar(File inFile, final File outDir) { Archive archive = null; try { archive = new Archive(inFile); } catch (Exception e) { log.error("Unable to read in RAR archive file: " + inFile.getAbsolutePath(), e); } if (archive == null) throw new AssertionError("Unable to create Archive from file: " + inFile.getAbsolutePath()); if (archive.isEncrypted()) throw new AssertionError("RAR archive is encrypted! Can't be decompressed!"); FileHeader fileHeader = null; while ( (fileHeader = archive.nextFileHeader()) != null ) if (archive.isEncrypted()) { log.error("RAR file header (" + fileHeader.getFileNameString() + ") is encrypted! Can't be decompressed!"); continue; } log.info("Extracting file: " + fileHeader.getFileNameString()); try { if (fileHeader.isDirectory()) createDirectory(fileHeader, outDir); else { File f = createFile(fileHeader, outDir); OutputStream stream = new FileOutputStream(f); archive.extractFile(fileHeader, stream); stream.close(); } } catch (Exception e) { log.error("Error extracting file!", e); } } private static File createFile(FileHeader fh, File destination) { File f = null; String name = null; if (fh.isFileHeader() && fh.isUnicode()) { name = fh.getFileNameW(); } else { name = fh.getFileNameString(); } f = new File(destination, name); if (!f.exists()) { try { f = makeFile(destination, name); } catch (IOException e) { log.error("Error creating new file: " + f.getName(), e); } } return f; } private static File makeFile(File destination, String name) throws IOException { String[] dirs = name.split("\\\\"); if (dirs == null) { return null; } String path = ""; int size = dirs.length; if (size == 1) { return new File(destination, name); } else if (size > 1) { for (int i = 0; i < dirs.length - 1; i++) { path = path + File.separator + dirs[i]; new File(destination, path).mkdir(); } path = path + File.separator + dirs[dirs.length - 1]; File f = new File(destination, path); f.createNewFile(); return f; } else { return null; } } private static void createDirectory(FileHeader fh, File destination) { File f = null; if (fh.isDirectory() && fh.isUnicode()) { f = new File(destination, fh.getFileNameW()); if (!f.exists()) { makeDirectory(destination, fh.getFileNameW()); } } else if (fh.isDirectory() && !fh.isUnicode()) { f = new File(destination, fh.getFileNameString()); if (!f.exists()) { makeDirectory(destination, fh.getFileNameString()); } } } private static void makeDirectory(File destination, String fileName) { String[] dirs = fileName.split("\\\\"); if (dirs == null) { return; } String path = ""; for (String dir : dirs) { path = path + File.separator + dir; new File(destination, path).mkdir(); } } }