/******************************************************************************* * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Oracle - initial API and implementation from Oracle TopLink ******************************************************************************/ package org.eclipse.persistence.tools.file; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Objects; import java.util.Vector; import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; import java.util.zip.CRC32; import java.util.zip.ZipEntry; import org.eclipse.persistence.internal.helper.Helper; import org.eclipse.persistence.logging.AbstractSessionLog; import org.eclipse.persistence.logging.SessionLog; /** * INTERNAL: * * <b>Purpose</b>: Provide common file I/O utilities * @author Steven Vo * @since TopLink 4.5 */ public class FileUtil { /* Copy file to another file or copy content of a directory to another directory * * @inputPath: path to a file or directory * @outputPath: path to a file or directory * @filteredExtensions: filter files that end with specified strings i.e {".java", ".class", ".xml"} */ public static void copy(String inputPath, String outputPath, String[] filteredExtensions) throws IOException { File inputPathFile = new File(inputPath); if (!inputPathFile.exists()) { return; } File outputPathFile = new File(outputPath); if (!outputPathFile.exists()) { if (outputPathFile.isDirectory()) { if (!outputPathFile.mkdirs()) { AbstractSessionLog.getLog().log(SessionLog.FINE, SessionLog.MISC, "Cannot create directory '{0}'", new Object[] {outputPathFile}, false); } } else { if (!outputPathFile.getParentFile().mkdirs()) { AbstractSessionLog.getLog().log(SessionLog.FINE, SessionLog.MISC, "Cannot create directory '{0}'", new Object[] {outputPathFile}, false); } } } Vector files = findFiles(inputPath, filteredExtensions); for (int i = 0; i < files.size(); i++) { File in = (File)files.elementAt(i); String outFilePath = in.getAbsolutePath().substring(inputPath.length()); outFilePath = outputPath + File.separator + outFilePath; File out = new File(outFilePath); File parent = new File(out.getParent()); if (!parent.exists()) { if (!parent.mkdirs()) { AbstractSessionLog.getLog().log(SessionLog.FINE, SessionLog.MISC, "Cannot create directory '{0}'", new Object[] {outputPathFile}, false); } } copy(new FileInputStream(in), new FileOutputStream(out)); } } /* Copy an input stream to an output stream * * @in: input stream * @out: output stream */ public static void copy(InputStream in, OutputStream out) throws IOException { try (InputStream i = in; OutputStream o = out;) { byte[] buffer = new byte[512]; while (true) { int bytesRead = i.read(buffer); if (bytesRead == -1) { break; } o.write(buffer, 0, bytesRead); } } } /* Jar a given directory * * @jarFileName: path of the output jar * @jarDirectory: path to the input directory * @filteredExtensions: filter files that end with specified strings i.e {".java", ".class", ".xml"} */ public static void createJarFromDirectory(String jarFileName, String jarDirectory, String[] filtertedExtensions) throws IOException { File directory = new File(jarDirectory); if (!directory.exists()) { return; } File jar = new File(jarFileName); if (!jar.exists()) { if (!jar.getParentFile().mkdirs()) { AbstractSessionLog.getLog().log(SessionLog.FINE, SessionLog.MISC, "Cannot create directory '{0}'", new Object[] {jar.getParentFile()}, false); } } JarOutputStream jarOut = null; try { jarOut = new JarOutputStream(new FileOutputStream(jar), new Manifest()); Vector files = findFiles(jarDirectory, filtertedExtensions); for (int i = 0; i < files.size(); i++) { File file = (File)files.elementAt(i); String relativePathToDirectory = file.getAbsolutePath().substring(directory.getAbsolutePath().length() + 1); String entryName = relativePathToDirectory.replace('\\', '/'); FileInputStream inStream = null; ByteArrayOutputStream byteStream = null; try { inStream = new FileInputStream(file); byteStream = new ByteArrayOutputStream(); int length = 0; byte[] buffer = new byte[1024]; while ((length = inStream.read(buffer)) > 0) { byteStream.write(buffer, 0, length); } byte[] arr = byteStream.toByteArray(); JarEntry meta = new JarEntry(entryName); jarOut.putNextEntry(meta); meta.setSize(arr.length); meta.setCompressedSize(arr.length); CRC32 crc = new CRC32(); crc.update(arr); meta.setCrc(crc.getValue()); meta.setMethod(ZipEntry.STORED); jarOut.write(arr, 0, arr.length); jarOut.closeEntry(); } finally { Helper.close(byteStream); Helper.close(inStream); } } } finally { Helper.close(jarOut); } } /* * Return vector of all Files contained in a path. * * @filteredExtensions: filter files that end with specified strings i.e {".java", ".class", ".xml"} * If filteredExtensions == null or empty then then return all instances of File contained in the directory and its sub directories * @Path: a directory path or a file path. * If it's file path then return a single instance of File * If it's directory path then return all instances of File contained in the directory and its sub directories */ public static Vector findFiles(String path, String[] filteredExtensions) { Vector files = new Vector(); findFilesHelper(new File(path), filteredExtensions, files); return files; } /* * INTERNAL: traverse the directory to find all files with filtered extensions. The result is passed * around for each recursive call */ private static void findFilesHelper(File file, String[] filteredExtensions, Vector result) { if (!file.exists()) { return; } if (file.isDirectory()) { String[] entries = file.list(); if (entries != null) { for (int i = 0; i < entries.length; i++) { findFilesHelper(new File(file, entries[i]), filteredExtensions, result); } } } else { // add everything if no filtered extension if ((filteredExtensions == null) || (filteredExtensions.length == 0)) { result.addElement(file); return; } // add only filtered extensions for (int i = 0; i < filteredExtensions.length; i++) { if (file.getName().endsWith(filteredExtensions[i])) { result.addElement(file); return; } } } } /* * Delete a file or directory * * @File: directory or file */ public static void delete(File file) { Objects.requireNonNull(file); if (!file.exists()) { return; } if (file.isDirectory()) { String[] entries = file.list(); if (entries == null || entries.length == 0) { if (!file.delete()) { AbstractSessionLog.getLog().log(SessionLog.FINE, SessionLog.MISC, "Cannot delete file '{0}'.", new Object[] {file}, false); } } else { for (int i = 0; i < entries.length; i++) { delete(new File(file, entries[i])); } // delete directory after its containing files were deleted String[] content = file.list(); if (content == null || content.length == 0) { if (!file.delete()) { AbstractSessionLog.getLog().log(SessionLog.FINE, SessionLog.MISC, "Cannot delete file '{0}'.", new Object[] {file}, false); } } } } else { if (!file.delete()) { AbstractSessionLog.getLog().log(SessionLog.FINE, SessionLog.MISC, "Cannot delete file '{0}'.", new Object[] {file}, false); } } } }