| /* |
| * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. |
| * Copyright (c) 2021 Contributors to the Eclipse Foundation |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0, which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * This Source Code may also be made available under the following Secondary |
| * Licenses when the conditions for such availability set forth in the |
| * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, |
| * version 2 with the GNU Classpath Exception, which is available at |
| * https://www.gnu.org/software/classpath/license.html. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 |
| */ |
| |
| /* Byron Nevins, April 2000 |
| * ZipFile -- A utility class for exploding archive (zip) files. |
| */ |
| package com.sun.enterprise.util.zip; |
| |
| import com.sun.enterprise.util.CULoggerInfo; |
| import com.sun.enterprise.util.io.FileUtils; |
| import java.io.*; |
| import java.util.*; |
| import java.util.jar.JarFile; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import java.util.zip.*; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| public class ZipFile { |
| |
| public ZipFile(String zipFilename, String explodeDirName) throws ZipFileException { |
| this(new File(zipFilename), new File(explodeDirName)); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| public ZipFile(InputStream inStream, String anExplodeDirName) throws ZipFileException { |
| this(new BufferedInputStream(inStream, BUFFER_SIZE), new File(anExplodeDirName)); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| public ZipFile(File zipFile, File anExplodeDir) throws ZipFileException { |
| checkZipFile(zipFile); |
| BufferedInputStream bis = null; |
| |
| try { |
| bis = new BufferedInputStream(new FileInputStream(zipFile), BUFFER_SIZE); |
| ctor(bis, anExplodeDir); |
| this.zipFile = zipFile; |
| } catch (Throwable e) { |
| if (bis != null) { |
| try { |
| bis.close(); |
| } catch (Throwable thr) { |
| throw new ZipFileException(thr); |
| } |
| } |
| throw new ZipFileException(e); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| public ZipFile(InputStream inStream, File anExplodeDir) throws ZipFileException { |
| ctor(inStream, anExplodeDir); |
| } |
| |
| /** |
| * Explodes files as usual, and then explodes every jar file found. All |
| * explosions are copied relative the same root directory.<p>It does a |
| * case-sensitive check for files that end with ".jar" will comment out for |
| * later possbile use public ArrayList explodeAll() throws ZipFileException |
| * { return doExplode(this); } |
| */ |
| ////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| public ArrayList<String> explode() throws ZipFileException { |
| files = new ArrayList<String>(); |
| ZipInputStream zin = null; |
| BufferedOutputStream bos = null; |
| |
| try { |
| zin = zipStream; // new ZipInputStream(new FileInputStream(zipFile)); |
| ZipEntry ze; |
| |
| while ((ze = zin.getNextEntry()) != null) { |
| String filename = ze.getName(); |
| |
| /* |
| if(isManifest(filename)) |
| { |
| continue; // don't bother with manifest file... |
| } |
| */ |
| |
| File fullpath; |
| |
| if (isDirectory(filename)) { |
| // just a directory -- make it and move on... |
| fullpath = new File(explodeDir, filename.substring(0, filename.length() - 1)); |
| if (!fullpath.mkdirs()) { |
| throw new IOException("Cannot create directory: " + fullpath); |
| } |
| continue; |
| } |
| |
| fullpath = new File(explodeDir, filename); |
| |
| File newDir = fullpath.getParentFile(); |
| |
| if (!newDir.mkdirs()) { |
| _utillogger.log(Level.FINE, "Cannot create directory {0}", newDir); |
| } |
| |
| if (fullpath.delete()) { // wipe-out pre-existing files |
| /* |
| * Report that a file is being overwritten. |
| */ |
| if (_utillogger.isLoggable(Level.FINE)) { |
| _utillogger.log(Level.FINE, "File {0} is being overwritten during expansion of {1}", new Object[]{fullpath.getAbsolutePath(), zipFile != null ? ("file " + zipFile.getAbsolutePath()) : "stream"}); |
| } |
| } |
| |
| File f = new File(explodeDir, filename); |
| |
| if (f.isDirectory()) { |
| continue; // e.g. if we asked to write to a directory instead of a file... |
| } |
| |
| bos = new BufferedOutputStream(getOutputStream(f), BUFFER_SIZE); |
| |
| int totalBytes = 0; |
| |
| for (int numBytes = zin.read(buffer); numBytes > 0; numBytes = zin.read(buffer)) { |
| bos.write(buffer, 0, numBytes); |
| totalBytes += numBytes; |
| } |
| bos.close(); |
| bos = null; |
| files.add(filename); |
| } |
| } catch (IOException e) { |
| throw new ZipFileException(e); |
| } finally { |
| if (bos != null) { |
| try { |
| bos.close(); |
| } catch (IOException e) { |
| } |
| } |
| try { |
| if (zin != null) { |
| zin.close(); |
| } |
| } catch (IOException e) { |
| throw new ZipFileException("Got an exception while trying to close Jar input stream: " + e);//NOI18N |
| } |
| } |
| return files; |
| } |
| |
| /** |
| * Extracts the named jar file from the ear. |
| * |
| * @param jarEntryName name of the jar file |
| * @param earFile application archive |
| * @param jarFile locaton of the jar file where the jar entry will be |
| * extracted |
| * |
| * @return the named jar file from the ear |
| * |
| * @exception ZipFileException if an error while extracting the jar |
| */ |
| public static void extractJar(String jarEntryName, JarFile earFile, |
| File jarFile) throws ZipFileException { |
| |
| try { |
| File parent = jarFile.getParentFile(); |
| if (!parent.exists()) { |
| if (!parent.mkdirs()) { |
| throw new ZipFileException("Cannot create directory: " + parent); |
| } |
| } |
| |
| ZipEntry jarEntry = earFile.getEntry(jarEntryName); |
| if (jarEntry == null) { |
| throw new ZipFileException(jarEntryName |
| + " not found in " + earFile.getName()); |
| } |
| |
| InputStream is = earFile.getInputStream(jarEntry); |
| FileOutputStream fos = new FileOutputStream(jarFile); |
| // the FileUtils.copy will buffer the streams, |
| // so we won't buffer them here. |
| FileUtils.copy(is, fos, jarEntry.getSize()); |
| } catch (IOException e) { |
| throw new ZipFileException(e); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| public ArrayList getFileList() { |
| return files; |
| } |
| |
| /** |
| * ********************************************************************* |
| * /******************************** Private ****************************** |
| /********************************************************************** |
| */ |
| /* Apparently this method is never called. Don't know the history |
| * about this method so commenting it out as opposed to removing it |
| * for now. |
| private static ArrayList<String> doExplode(ZipFile zf) throws ZipFileException |
| { |
| ArrayList<String> finalList = new ArrayList<String>(50); |
| ArrayList<ZipFile> zipFileList = new ArrayList<ZipFile>(); |
| ArrayList tmpList = null; |
| ZipFile tmpZf = null; |
| Iterator itr = null; |
| String fileName = null; |
| |
| zipFileList.add(zf); |
| while (zipFileList.size() > 0) |
| { |
| // get "last" jar to explode |
| tmpZf = zipFileList.remove(zipFileList.size() - 1); |
| tmpList = tmpZf.explode(); |
| |
| // traverse list of files |
| itr = tmpList.iterator(); |
| while (itr.hasNext()) |
| { |
| fileName = (String)itr.next(); |
| if ( ! fileName.endsWith(".jar") ) |
| { |
| // add non-jar file to finalList |
| finalList.add(fileName); |
| } |
| else |
| { |
| // create ZipFile and add to zipFileList |
| File f = new File(tmpZf.explodeDir, fileName); |
| ZipFile newZf = new ZipFile(f, tmpZf.explodeDir); |
| zipFileList.add(newZf); |
| } |
| |
| if (tmpZf != zf) // don't remove first ZipFile |
| { |
| tmpZf.explodeDir.delete(); |
| } |
| } |
| } |
| return finalList; |
| } |
| */ |
| ////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| private void ctor(InputStream inStream, File anExplodeDir) throws ZipFileException { |
| insist(anExplodeDir != null); |
| explodeDir = anExplodeDir; |
| |
| try { |
| zipStream = new ZipInputStream(inStream); |
| checkExplodeDir(); |
| } catch (Throwable t) { |
| if (zipStream != null) { |
| try { |
| zipStream.close(); |
| } catch (Throwable thr) { |
| } |
| } |
| throw new ZipFileException(t.toString()); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| private boolean isDirectory(String s) { |
| char c = s.charAt(s.length() - 1); |
| |
| return c == '/' || c == '\\'; |
| } |
| |
| ///////////////////////////////////////////////////////////////////////////////////////// |
| private void checkZipFile(File zipFile) throws ZipFileException { |
| insist(zipFile != null); |
| |
| String zipFileName = zipFile.getPath(); |
| |
| insist(zipFile.exists(), "zipFile (" + zipFileName + ") doesn't exist");//NOI18N |
| insist(!zipFile.isDirectory(), "zipFile (" + zipFileName + ") is actually a directory!");//NOI18N |
| } |
| |
| ///////////////////////////////////////////////////////////////////////////////////////// |
| private void checkExplodeDir() throws ZipFileException { |
| String explodeDirName = explodeDir.getPath(); |
| |
| // just in case... |
| insist(explodeDir.mkdirs(), "Unable to create target directory: " + explodeDirName); |
| |
| insist(explodeDir.exists(), "Target Directory doesn't exist: " + explodeDirName);//NOI18N |
| insist(explodeDir.isDirectory(), "Target Directory isn't a directory: " + explodeDirName);//NOI18N |
| insist(explodeDir.canWrite(), "Can't write to Target Directory: " + explodeDirName);//NOI18N |
| } |
| |
| ///////////////////////////////////////////////////////////////////////////////////////// |
| private FileOutputStream getOutputStream(File f) throws ZipFileException { |
| try { |
| return new FileOutputStream(f); |
| } catch (FileNotFoundException e) { |
| throw new ZipFileException("filename: " + f.getPath() + " " + e); |
| } |
| } |
| |
| ///////////////////////////////////////////////////////////////////////////////////////// |
| //////////// ////////////////////////// |
| //////////// Internal Error-Checking Stuff ////////////////////////// |
| //////////// ////////////////////////// |
| ///////////////////////////////////////////////////////////////////////////////////////// |
| private static void insist(boolean b) throws ZipFileException { |
| if (!b) { |
| throw new ZipFileException(); |
| } |
| } |
| |
| ///////////////////////////////////////////////////////////////////////////////////////// |
| private static void insist(boolean b, String mesg) throws ZipFileException { |
| if (!b) { |
| throw new ZipFileException(mesg); |
| } |
| } |
| ///////////////////////////////////////////////////////////////////////////////////////// |
| private static final int BUFFER_SIZE = 0x10000; //64k |
| private File explodeDir = null; |
| private ArrayList<String> files = null; |
| private byte[] buffer = new byte[BUFFER_SIZE]; |
| private ZipInputStream zipStream = null; |
| private static final Logger _utillogger = CULoggerInfo.getLogger(); |
| private File zipFile = null; |
| } |
| |
| //////////////// |