001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.eclipse.aether.internal.impl; 020 021import javax.inject.Named; 022import javax.inject.Singleton; 023 024import java.io.*; 025import java.nio.ByteBuffer; 026import java.nio.charset.StandardCharsets; 027import java.nio.file.Files; 028import java.nio.file.StandardCopyOption; 029 030import org.eclipse.aether.spi.io.FileProcessor; 031import org.eclipse.aether.util.FileUtils; 032 033/** 034 * A utility class helping with file-based operations. 035 * 036 * @deprecated 037 */ 038@Deprecated 039@Singleton 040@Named 041public class DefaultFileProcessor implements FileProcessor { 042 043 /** 044 * Thread-safe variant of {@link File#mkdirs()}. Creates the directory named by the given abstract pathname, 045 * including any necessary but nonexistent parent directories. Note that if this operation fails it may have 046 * succeeded in creating some of the necessary parent directories. 047 * 048 * @param directory The directory to create, may be {@code null}. 049 * @return {@code true} if and only if the directory was created, along with all necessary parent directories; 050 * {@code false} otherwise 051 */ 052 @Override 053 public boolean mkdirs(File directory) { 054 if (directory == null) { 055 return false; 056 } 057 058 if (directory.exists()) { 059 return false; 060 } 061 if (directory.mkdir()) { 062 return true; 063 } 064 065 File canonDir; 066 try { 067 canonDir = directory.getCanonicalFile(); 068 } catch (IOException e) { 069 throw new UncheckedIOException(e); 070 } 071 072 File parentDir = canonDir.getParentFile(); 073 return (parentDir != null && (mkdirs(parentDir) || parentDir.exists()) && canonDir.mkdir()); 074 } 075 076 @Override 077 public void write(File target, String data) throws IOException { 078 FileUtils.writeFile(target.toPath(), p -> Files.write(p, data.getBytes(StandardCharsets.UTF_8))); 079 } 080 081 @Override 082 public void write(File target, InputStream source) throws IOException { 083 FileUtils.writeFile(target.toPath(), p -> Files.copy(source, p, StandardCopyOption.REPLACE_EXISTING)); 084 } 085 086 @Override 087 public void copy(File source, File target) throws IOException { 088 copy(source, target, null); 089 } 090 091 @Override 092 public long copy(File source, File target, ProgressListener listener) throws IOException { 093 try (InputStream in = new BufferedInputStream(Files.newInputStream(source.toPath())); 094 FileUtils.CollocatedTempFile tempTarget = FileUtils.newTempFile(target.toPath()); 095 OutputStream out = new BufferedOutputStream(Files.newOutputStream(tempTarget.getPath()))) { 096 long result = copy(out, in, listener); 097 tempTarget.move(); 098 return result; 099 } 100 } 101 102 private long copy(OutputStream os, InputStream is, ProgressListener listener) throws IOException { 103 long total = 0L; 104 byte[] buffer = new byte[1024 * 32]; 105 while (true) { 106 int bytes = is.read(buffer); 107 if (bytes < 0) { 108 break; 109 } 110 111 os.write(buffer, 0, bytes); 112 113 total += bytes; 114 115 if (listener != null && bytes > 0) { 116 try { 117 listener.progressed(ByteBuffer.wrap(buffer, 0, bytes)); 118 } catch (Exception e) { 119 // too bad 120 } 121 } 122 } 123 124 return total; 125 } 126 127 @Override 128 public void move(File source, File target) throws IOException { 129 if (!source.renameTo(target)) { 130 copy(source, target); 131 132 target.setLastModified(source.lastModified()); 133 134 source.delete(); 135 } 136 } 137 138 @Override 139 public String readChecksum(final File checksumFile) throws IOException { 140 // for now do exactly same as happened before, but FileProcessor is a component and can be replaced 141 String checksum = ""; 142 try (BufferedReader br = new BufferedReader( 143 new InputStreamReader(Files.newInputStream(checksumFile.toPath()), StandardCharsets.UTF_8), 512)) { 144 while (true) { 145 String line = br.readLine(); 146 if (line == null) { 147 break; 148 } 149 line = line.trim(); 150 if (!line.isEmpty()) { 151 checksum = line; 152 break; 153 } 154 } 155 } 156 157 if (checksum.matches(".+= [0-9A-Fa-f]+")) { 158 int lastSpacePos = checksum.lastIndexOf(' '); 159 checksum = checksum.substring(lastSpacePos + 1); 160 } else { 161 int spacePos = checksum.indexOf(' '); 162 163 if (spacePos != -1) { 164 checksum = checksum.substring(0, spacePos); 165 } 166 } 167 168 return checksum; 169 } 170 171 @Override 172 public void writeChecksum(final File checksumFile, final String checksum) throws IOException { 173 // for now do exactly same as happened before, but FileProcessor is a component and can be replaced 174 write(checksumFile, checksum); 175 } 176}