package org.atomnuke.container.packaging.archive.zip; import com.rackspace.papi.commons.util.SystemUtils; import java.io.File; import java.io.IOException; import java.net.URI; import java.util.LinkedList; import java.util.Queue; import java.util.UUID; import org.atomnuke.container.packaging.resource.ResourceManagerImpl; import org.atomnuke.container.packaging.DeployedPackage; import org.atomnuke.container.packaging.DeployedPackageImpl; import org.atomnuke.container.packaging.Unpacker; import org.atomnuke.container.packaging.UnpackerException; import org.atomnuke.container.packaging.archive.ResourceType; import org.atomnuke.container.packaging.resource.ResourceManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author zinic */ public class ArchiveExtractor implements Unpacker { private static final Logger LOG = LoggerFactory.getLogger(ArchiveExtractor.class); private final Queue<EmbeddedArchive> archivesToUnpack; private final File deploymentRoot; public ArchiveExtractor(File deploymentRoot) { this.deploymentRoot = deploymentRoot; archivesToUnpack = new LinkedList<EmbeddedArchive>(); } @Override public DeployedPackage unpack(ResourceManager rootResourceManager, URI archiveLocation) throws UnpackerException { final ZipUnpacker zipUnpacker = new ZipUnpacker(rootResourceManager, new File(deploymentRoot, UUID.randomUUID() + "." + SystemUtils.getPid())); final ResourceType uriType = ResourceType.findResourceTypeForName(archiveLocation.toString()); final ResourceManager localResourceManager = new ResourceManagerImpl(); try { unpackArchive(localResourceManager, zipUnpacker, uriType, archiveLocation, 0); unpackEmbeddedArchives(localResourceManager, zipUnpacker); return new DeployedPackageImpl(localResourceManager, archiveLocation); } catch (IOException ioe) { throw new UnpackerException(ioe); } } @Override public boolean canUnpack(URI archiveLocation) { final ResourceType uriType = ResourceType.findResourceTypeForName(archiveLocation.toString()); switch (uriType) { case EAR: case JAR: case ZIP: return true; default: return false; } } private void unpackArchive(ResourceManager localResourceManager, ZipUnpacker zipUnpacker, ResourceType uriType, URI archiveLocation, int archiveDepth) throws IOException { switch (uriType) { case EAR: case JAR: case ZIP: archivesToUnpack.addAll(zipUnpacker.unpack(localResourceManager, archiveLocation, archiveDepth)); break; default: LOG.error("Unknown archive format: " + archiveLocation.toString()); } } private void unpackEmbeddedArchives(ResourceManager localResourceManager, ZipUnpacker zipUnpacker) throws IOException { while (!archivesToUnpack.isEmpty()) { final EmbeddedArchive nextArchive = archivesToUnpack.poll(); if (nextArchive.archiveDepth() > 5) { LOG.error("Cowardly refusing to recurse into archive: " + nextArchive.archiveLocation() + ". Reason: archive recursive depth limited to 5."); } else if (canUnpack(nextArchive.archiveLocation())) { unpackArchive(localResourceManager, zipUnpacker, nextArchive.archiveEntry().type(), nextArchive.archiveLocation(), nextArchive.archiveDepth()); } } } }