001package org.apache.archiva.common.utils; 002/* 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, 014 * software distributed under the License is distributed on an 015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 016 * KIND, either express or implied. See the License for the 017 * specific language governing permissions and limitations 018 * under the License. 019 */ 020 021import org.slf4j.Logger; 022import org.slf4j.LoggerFactory; 023 024import java.io.*; 025import java.nio.charset.Charset; 026import java.nio.file.Files; 027import java.nio.file.Path; 028import java.nio.file.Paths; 029import java.nio.file.StandardOpenOption; 030import java.util.Comparator; 031import java.util.Optional; 032import java.util.zip.ZipEntry; 033import java.util.zip.ZipFile; 034 035/** 036 * Utility class for file manipulation 037 * 038 * @author Martin Stockhammer <martin_s@apache.org> 039 */ 040public class FileUtils { 041 private static final Logger log = LoggerFactory.getLogger(FileUtils.class); 042 043 /** 044 * Deletes the directory recursively and quietly. 045 * 046 * @param dir 047 */ 048 public static void deleteQuietly(Path dir) { 049 try { 050 Files.walk(dir) 051 .sorted(Comparator.reverseOrder()) 052 .forEach(file -> { 053 try { 054 Files.delete(file); 055 } catch (IOException e) { 056 // Ignore this 057 } 058 059 }); 060 } catch (IOException e) { 061 // Ignore this 062 } 063 064 065 } 066 067 public static void deleteDirectory(Path dir) throws IOException { 068 if (!Files.exists(dir)) { 069 return; 070 } 071 if (!Files.isDirectory(dir)) { 072 throw new IOException("Given path is not a directory " + dir); 073 } 074 boolean result = true; 075 try { 076 result = Files.walk(dir) 077 .sorted(Comparator.reverseOrder()) 078 .map(file -> 079 { 080 try { 081 Files.delete(file); 082 return Optional.of(Boolean.TRUE); 083 } catch (UncheckedIOException | IOException e) { 084 log.warn("File could not be deleted {}", file); 085 return Optional.empty(); 086 } 087 088 }).allMatch(Optional::isPresent); 089 } catch (UncheckedIOException e) { 090 throw new IOException("File deletion failed ", e); 091 } 092 if (!result) { 093 throw new IOException("Error during recursive delete of " + dir.toAbsolutePath()); 094 } 095 } 096 097 public static String readFileToString(Path file, Charset encoding) { 098 try { 099 return new String(Files.readAllBytes(file), encoding); 100 } catch (IOException e) { 101 log.error("Could not read from file {}", file); 102 return ""; 103 } 104 } 105 106 public static void writeStringToFile(Path file, Charset encoding, String value) { 107 try { 108 Files.write(file, value.getBytes(encoding), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); 109 } catch (IOException e) { 110 log.error("Could not write to file {}", file); 111 } 112 } 113 114 /** 115 * Return the base directory 116 * 117 * @return 118 */ 119 public static String getBasedir() { 120 String basedir = System.getProperty("basedir"); 121 if (basedir == null) { 122 basedir = Paths.get("").toAbsolutePath().toString(); 123 } 124 125 return basedir; 126 } 127 128 /** 129 * This checks, if the given child is a absolute path. If this is the case 130 * the relative path is used. 131 * 132 * @param parent The parent directory 133 * @param child The child 134 * @return The path parent/child 135 */ 136 public Path resolveNonAbsolute(Path parent, String child) { 137 Path childPath = Paths.get(child); 138 if (childPath.isAbsolute()) { 139 return parent.resolve(childPath.getNameCount() > 0 ? childPath.subpath(0, childPath.getNameCount()) : Paths.get("")); 140 } else { 141 return parent.resolve(child); 142 } 143 } 144 145 public static void unzipFileEntry(ZipFile file, ZipEntry entry, Path destinationPath) throws IOException { 146 InputStream is = file.getInputStream(entry); 147 BufferedInputStream bis = new BufferedInputStream(is); 148 Path uncompressedFilePath = destinationPath.resolve(entry.getName()); 149 Path parentPath = uncompressedFilePath.getParent(); 150 if (!Files.exists(parentPath)) { 151 Files.createDirectories(parentPath); 152 } 153 Files.createFile(uncompressedFilePath); 154 OutputStream fileOutput = Files.newOutputStream(uncompressedFilePath); 155 while (bis.available() > 0) { 156 fileOutput.write(bis.read()); 157 } 158 fileOutput.close(); 159 } 160 161 162 /** 163 * Unzips a file into a destination directory. It does not update the modification time according the 164 * the date in the zip file. All subdirectories will be created if the zip file contains a directory structure. 165 * 166 * @param zipFile the path to the zip file 167 * @param destinationPath the destination path where the files should be extracted. 168 * @throws IOException if an error occurs during extract. 169 */ 170 public static void unzip(Path zipFile, Path destinationPath) throws IOException { 171 try (ZipFile file = new ZipFile(zipFile.toFile())) { 172 file.stream().forEach(e -> { 173 try { 174 if (e.isDirectory()) { 175 Files.createDirectories(destinationPath.resolve(e.getName())); 176 } else { 177 unzipFileEntry(file, e, destinationPath); 178 } 179 } catch (IOException ex) { 180 log.error("Error occured during unzip of zipFile={}, entry={}. Message: {}", zipFile, e.getName(), ex.getMessage()); 181 } 182 }); 183 } 184 } 185}