blob: fdd5963b0d3a48f894cee7e782b2d45239d8da71 [file] [log] [blame]
/*
* Copyright (c) 1998, 2021 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 v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// 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.List;
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 final class FileUtil {
private 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);
}
}
}
List<File> files = findFiles(inputPath, filteredExtensions);
for (int i = 0; i < files.size(); i++) {
File in = files.get(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());
List<File> files = findFiles(jarDirectory, filtertedExtensions);
for (int i = 0; i < files.size(); i++) {
File file = files.get(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 List<File> findFiles(String path, String[] filteredExtensions) {
List<File> 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, List<File> 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.add(file);
return;
}
// add only filtered extensions
for (int i = 0; i < filteredExtensions.length; i++) {
if (file.getName().endsWith(filteredExtensions[i])) {
result.add(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);
}
}
}
}