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.Buffer; 029import java.nio.ByteBuffer; 030import java.nio.charset.StandardCharsets; 031 032import javax.inject.Named; 033 034import org.eclipse.aether.spi.io.FileProcessor; 035 036/** 037 * A utility class helping with file-based operations. 038 */ 039@Named 040public class DefaultFileProcessor 041 implements FileProcessor 042{ 043 044 /** 045 * Thread-safe variant of {@link File#mkdirs()}. Creates the directory named by the given abstract pathname, 046 * including any necessary but nonexistent parent directories. Note that if this operation fails it may have 047 * succeeded in creating some of the necessary parent directories. 048 * 049 * @param directory The directory to create, may be {@code null}. 050 * @return {@code true} if and only if the directory was created, along with all necessary parent directories; 051 * {@code false} otherwise 052 */ 053 public boolean mkdirs( File directory ) 054 { 055 if ( directory == null ) 056 { 057 return false; 058 } 059 060 if ( directory.exists() ) 061 { 062 return false; 063 } 064 if ( directory.mkdir() ) 065 { 066 return true; 067 } 068 069 File canonDir; 070 try 071 { 072 canonDir = directory.getCanonicalFile(); 073 } 074 catch ( IOException e ) 075 { 076 return false; 077 } 078 079 File parentDir = canonDir.getParentFile(); 080 return ( parentDir != null && ( mkdirs( parentDir ) || parentDir.exists() ) && canonDir.mkdir() ); 081 } 082 083 public void write( File target, String data ) 084 throws IOException 085 { 086 mkdirs( target.getAbsoluteFile().getParentFile() ); 087 088 OutputStream out = null; 089 try 090 { 091 out = new FileOutputStream( target ); 092 093 if ( data != null ) 094 { 095 out.write( data.getBytes( StandardCharsets.UTF_8 ) ); 096 } 097 098 out.close(); 099 out = null; 100 } 101 finally 102 { 103 try 104 { 105 if ( out != null ) 106 { 107 out.close(); 108 } 109 } 110 catch ( final IOException e ) 111 { 112 // Suppressed due to an exception already thrown in the try block. 113 } 114 } 115 } 116 117 public void write( File target, InputStream source ) 118 throws IOException 119 { 120 mkdirs( target.getAbsoluteFile().getParentFile() ); 121 122 OutputStream out = null; 123 try 124 { 125 out = new FileOutputStream( target ); 126 127 copy( out, source, null ); 128 129 out.close(); 130 out = null; 131 } 132 finally 133 { 134 try 135 { 136 if ( out != null ) 137 { 138 out.close(); 139 } 140 } 141 catch ( final IOException e ) 142 { 143 // Suppressed due to an exception already thrown in the try block. 144 } 145 } 146 } 147 148 public void copy( File source, File target ) 149 throws IOException 150 { 151 copy( source, target, null ); 152 } 153 154 public long copy( File source, File target, ProgressListener listener ) 155 throws IOException 156 { 157 long total = 0L; 158 159 InputStream in = null; 160 OutputStream out = null; 161 try 162 { 163 in = new FileInputStream( source ); 164 165 mkdirs( target.getAbsoluteFile().getParentFile() ); 166 167 out = new FileOutputStream( target ); 168 169 total = copy( out, in, listener ); 170 171 out.close(); 172 out = null; 173 174 in.close(); 175 in = null; 176 } 177 finally 178 { 179 try 180 { 181 if ( out != null ) 182 { 183 out.close(); 184 } 185 } 186 catch ( final IOException e ) 187 { 188 // Suppressed due to an exception already thrown in the try block. 189 } 190 finally 191 { 192 try 193 { 194 if ( in != null ) 195 { 196 in.close(); 197 } 198 } 199 catch ( final IOException e ) 200 { 201 // Suppressed due to an exception already thrown in the try block. 202 } 203 } 204 } 205 206 return total; 207 } 208 209 private long copy( OutputStream os, InputStream is, ProgressListener listener ) 210 throws IOException 211 { 212 long total = 0L; 213 214 ByteBuffer buffer = ByteBuffer.allocate( 1024 * 32 ); 215 byte[] array = buffer.array(); 216 217 while ( true ) 218 { 219 int bytes = is.read( array ); 220 if ( bytes < 0 ) 221 { 222 break; 223 } 224 225 os.write( array, 0, bytes ); 226 227 total += bytes; 228 229 if ( listener != null && bytes > 0 ) 230 { 231 try 232 { 233 ( (Buffer) buffer ).rewind(); 234 ( (Buffer) buffer ).limit( bytes ); 235 listener.progressed( buffer ); 236 } 237 catch ( Exception e ) 238 { 239 // too bad 240 } 241 } 242 } 243 244 return total; 245 } 246 247 public void move( File source, File target ) 248 throws IOException 249 { 250 if ( !source.renameTo( target ) ) 251 { 252 copy( source, target ); 253 254 target.setLastModified( source.lastModified() ); 255 256 source.delete(); 257 } 258 } 259 260}