001package org.eclipse.aether.internal.impl; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.io.File; 023import java.io.FileInputStream; 024import java.io.FileOutputStream; 025import java.io.IOException; 026import java.io.InputStream; 027import java.io.OutputStream; 028import java.nio.ByteBuffer; 029import java.nio.charset.StandardCharsets; 030 031import javax.inject.Named; 032 033import org.eclipse.aether.spi.io.FileProcessor; 034 035/** 036 * A utility class helping with file-based operations. 037 */ 038@Named 039public class DefaultFileProcessor 040 implements FileProcessor 041{ 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 public boolean mkdirs( File directory ) 053 { 054 if ( directory == null ) 055 { 056 return false; 057 } 058 059 if ( directory.exists() ) 060 { 061 return false; 062 } 063 if ( directory.mkdir() ) 064 { 065 return true; 066 } 067 068 File canonDir; 069 try 070 { 071 canonDir = directory.getCanonicalFile(); 072 } 073 catch ( IOException e ) 074 { 075 return false; 076 } 077 078 File parentDir = canonDir.getParentFile(); 079 return ( parentDir != null && ( mkdirs( parentDir ) || parentDir.exists() ) && canonDir.mkdir() ); 080 } 081 082 public void write( File target, String data ) 083 throws IOException 084 { 085 mkdirs( target.getAbsoluteFile().getParentFile() ); 086 087 OutputStream out = null; 088 try 089 { 090 out = new FileOutputStream( target ); 091 092 if ( data != null ) 093 { 094 out.write( data.getBytes( StandardCharsets.UTF_8 ) ); 095 } 096 097 out.close(); 098 out = null; 099 } 100 finally 101 { 102 try 103 { 104 if ( out != null ) 105 { 106 out.close(); 107 } 108 } 109 catch ( final IOException e ) 110 { 111 // Suppressed due to an exception already thrown in the try block. 112 } 113 } 114 } 115 116 public void write( File target, InputStream source ) 117 throws IOException 118 { 119 mkdirs( target.getAbsoluteFile().getParentFile() ); 120 121 OutputStream out = null; 122 try 123 { 124 out = new FileOutputStream( target ); 125 126 copy( out, source, null ); 127 128 out.close(); 129 out = null; 130 } 131 finally 132 { 133 try 134 { 135 if ( out != null ) 136 { 137 out.close(); 138 } 139 } 140 catch ( final IOException e ) 141 { 142 // Suppressed due to an exception already thrown in the try block. 143 } 144 } 145 } 146 147 public void copy( File source, File target ) 148 throws IOException 149 { 150 copy( source, target, null ); 151 } 152 153 public long copy( File source, File target, ProgressListener listener ) 154 throws IOException 155 { 156 long total = 0L; 157 158 InputStream in = null; 159 OutputStream out = null; 160 try 161 { 162 in = new FileInputStream( source ); 163 164 mkdirs( target.getAbsoluteFile().getParentFile() ); 165 166 out = new FileOutputStream( target ); 167 168 total = copy( out, in, listener ); 169 170 out.close(); 171 out = null; 172 173 in.close(); 174 in = null; 175 } 176 finally 177 { 178 try 179 { 180 if ( out != null ) 181 { 182 out.close(); 183 } 184 } 185 catch ( final IOException e ) 186 { 187 // Suppressed due to an exception already thrown in the try block. 188 } 189 finally 190 { 191 try 192 { 193 if ( in != null ) 194 { 195 in.close(); 196 } 197 } 198 catch ( final IOException e ) 199 { 200 // Suppressed due to an exception already thrown in the try block. 201 } 202 } 203 } 204 205 return total; 206 } 207 208 private long copy( OutputStream os, InputStream is, ProgressListener listener ) 209 throws IOException 210 { 211 long total = 0L; 212 213 ByteBuffer buffer = ByteBuffer.allocate( 1024 * 32 ); 214 byte[] array = buffer.array(); 215 216 while ( true ) 217 { 218 int bytes = is.read( array ); 219 if ( bytes < 0 ) 220 { 221 break; 222 } 223 224 os.write( array, 0, bytes ); 225 226 total += bytes; 227 228 if ( listener != null && bytes > 0 ) 229 { 230 try 231 { 232 buffer.rewind(); 233 buffer.limit( bytes ); 234 listener.progressed( buffer ); 235 } 236 catch ( Exception e ) 237 { 238 // too bad 239 } 240 } 241 } 242 243 return total; 244 } 245 246 public void move( File source, File target ) 247 throws IOException 248 { 249 if ( !source.renameTo( target ) ) 250 { 251 copy( source, target ); 252 253 target.setLastModified( source.lastModified() ); 254 255 source.delete(); 256 } 257 } 258 259}