| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.openejb.util; |
| |
| import org.apache.openejb.loader.FileUtils; |
| import org.apache.openejb.loader.Files; |
| import org.apache.openejb.loader.IO; |
| import org.apache.openejb.loader.SystemInstance; |
| import org.apache.openejb.loader.Zips; |
| |
| import java.io.BufferedOutputStream; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.nio.channels.FileChannel; |
| import java.util.Properties; |
| |
| /** |
| * @version $Rev: 1423354 $ $Date: 2012-12-18 09:02:34 +0000 (Tue, 18 Dec 2012) $ |
| */ |
| public class JarExtractor { |
| |
| public static final Logger logger = Logger.getInstance(LogCategory.OPENEJB_STARTUP_CONFIG, "org.apache.openejb.util.resources"); |
| |
| /** |
| * Extract the Jar file into an unpacked directory structure, and |
| * return the absolute pathname to the extracted directory. |
| * |
| * @param file Jar file to unpack |
| * @param pathname Context path name for web application |
| * @throws IllegalArgumentException if this is not a "jar:" URL |
| * @throws java.io.IOException if an input/output error was encountered |
| * during expansion |
| */ |
| public static File extract(final File file, final String pathname) throws IOException { |
| |
| final Properties properties = SystemInstance.get().getProperties(); |
| final String key = "tomee.unpack.dir"; |
| |
| File unpackDir = file.getParentFile(); |
| |
| if (properties.containsKey(key)) { |
| final FileUtils base = SystemInstance.get().getBase(); |
| unpackDir = base.getDirectory(properties.getProperty(key), true); |
| } |
| |
| File docBase = new File(unpackDir, pathname); |
| |
| docBase = extract(file, docBase); |
| return docBase; |
| } |
| |
| /** |
| * Extract the jar file into the specifiec destination directory. If the destination directory |
| * already exists, the jar will not be unpacked. |
| * |
| * @param file jar file to unpack |
| * @param destinationDir the directory in which the jar will be unpacked; must not exist |
| * @throws java.io.IOException if an input/output error was encountered during expansion |
| */ |
| public static File extract(final File file, File destinationDir) throws IOException { |
| if (destinationDir.exists()) { |
| |
| if (destinationDir.lastModified() > file.lastModified()) { |
| // Ear file is already installed |
| // Unpacked dir is newer than archive |
| return destinationDir.getAbsoluteFile(); |
| } |
| |
| if (!deleteDir(destinationDir)) { |
| Files.deleteOnExit(destinationDir); |
| final File pf = destinationDir.getParentFile(); |
| final String name = destinationDir.getName() + System.currentTimeMillis(); |
| destinationDir = new File(pf, name); |
| destinationDir.deleteOnExit(); |
| Files.deleteOnExit(destinationDir); |
| } |
| } |
| |
| logger.info("Extracting jar: " + file.getAbsolutePath()); |
| |
| try { |
| Files.mkdirs(destinationDir); |
| } catch (Files.FileRuntimeException e) { |
| throw new IOException("Failed to create: " + destinationDir); |
| } |
| |
| try { |
| Zips.unzip(file, destinationDir); |
| } catch (IOException e) { |
| // If something went wrong, delete extracted dir to keep things clean |
| Files.delete(destinationDir); |
| throw e; |
| } |
| |
| // Return the absolute path to our new document base directory |
| logger.info("Extracted path: " + destinationDir.getAbsolutePath()); |
| return destinationDir.getAbsoluteFile(); |
| } |
| |
| /** |
| * Copy the specified file or directory to the destination. |
| * |
| * @param src File object representing the source |
| * @param dest File object representing the destination |
| */ |
| public static boolean copyRecursively(final File src, final File dest) { |
| |
| boolean result = true; |
| |
| String files[]; |
| |
| if (src.isDirectory()) { |
| files = src.list(); |
| result = dest.mkdir(); |
| } else { |
| files = new String[1]; |
| files[0] = ""; |
| } |
| |
| if (files == null) { |
| files = new String[0]; |
| } |
| for (int i = 0; (i < files.length) && result; i++) { |
| final File fileSrc = new File(src, files[i]); |
| final File fileDest = new File(dest, files[i]); |
| |
| if (fileSrc.isDirectory()) { |
| |
| result = copyRecursively(fileSrc, fileDest); |
| |
| } else { |
| |
| FileChannel ic = null; |
| FileChannel oc = null; |
| try { |
| ic = (new FileInputStream(fileSrc)).getChannel(); |
| oc = (new FileOutputStream(fileDest)).getChannel(); |
| ic.transferTo(0, ic.size(), oc); |
| } catch (IOException e) { |
| logger.error("Copy failed: src: " + fileSrc + ", dest: " + fileDest, e); |
| result = false; |
| } finally { |
| IO.close(ic); |
| IO.close(oc); |
| } |
| } |
| } |
| return result; |
| |
| } |
| |
| /** |
| * Delete the specified directory, including all of its contents and |
| * subdirectories recursively. |
| * |
| * @param dir File object representing the directory to be deleted |
| */ |
| public static boolean delete(final File dir) { |
| return deleteDir(dir); |
| } |
| |
| /** |
| * Delete the specified directory, including all of its contents and |
| * subdirectories recursively. |
| * |
| * @param dir File object representing the directory to be deleted |
| */ |
| public static boolean deleteDir(final File dir) { |
| if (dir == null) |
| return true; |
| |
| if (dir.isDirectory()) { |
| final File[] files = dir.listFiles(); |
| if (files != null) { |
| for (final File file : files) { |
| deleteDir(file); |
| } |
| } |
| } |
| |
| return dir.delete(); |
| } |
| |
| /** |
| * Extract the specified input stream into the specified directory, creating |
| * a file named from the specified relative path. |
| * |
| * @param input InputStream to be copied |
| * @param docBase Document base directory into which we are extracting |
| * @param name Relative pathname of the file to be created |
| * @return A handle to the extracted File |
| * @throws java.io.IOException if an input/output error occurs |
| */ |
| protected static File extract(final InputStream input, final File docBase, final String name) |
| throws IOException { |
| |
| final File file = new File(docBase, name); |
| BufferedOutputStream output = null; |
| try { |
| output = new BufferedOutputStream(new FileOutputStream(file)); |
| final byte[] buffer = new byte[2048]; |
| while (true) { |
| final int n = input.read(buffer); |
| if (n <= 0) |
| break; |
| output.write(buffer, 0, n); |
| } |
| } finally { |
| if (output != null) { |
| try { |
| output.close(); |
| } catch (IOException e) { |
| // Ignore |
| } |
| } |
| } |
| |
| return file; |
| } |
| |
| } |