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.Closeable; 023import java.io.File; 024import java.io.FileInputStream; 025import java.io.FileOutputStream; 026import java.io.IOException; 027import java.io.InputStream; 028import java.io.OutputStream; 029import java.nio.ByteBuffer; 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 private static void close( Closeable closeable ) 044 { 045 if ( closeable != null ) 046 { 047 try 048 { 049 closeable.close(); 050 } 051 catch ( IOException e ) 052 { 053 // too bad but who cares 054 } 055 } 056 } 057 058 /** 059 * Thread-safe variant of {@link File#mkdirs()}. Creates the directory named by the given abstract pathname, 060 * including any necessary but nonexistent parent directories. Note that if this operation fails it may have 061 * succeeded in creating some of the necessary parent directories. 062 * 063 * @param directory The directory to create, may be {@code null}. 064 * @return {@code true} if and only if the directory was created, along with all necessary parent directories; 065 * {@code false} otherwise 066 */ 067 public boolean mkdirs( File directory ) 068 { 069 if ( directory == null ) 070 { 071 return false; 072 } 073 074 if ( directory.exists() ) 075 { 076 return false; 077 } 078 if ( directory.mkdir() ) 079 { 080 return true; 081 } 082 083 File canonDir; 084 try 085 { 086 canonDir = directory.getCanonicalFile(); 087 } 088 catch ( IOException e ) 089 { 090 return false; 091 } 092 093 File parentDir = canonDir.getParentFile(); 094 return ( parentDir != null && ( mkdirs( parentDir ) || parentDir.exists() ) && canonDir.mkdir() ); 095 } 096 097 public void write( File target, String data ) 098 throws IOException 099 { 100 mkdirs( target.getAbsoluteFile().getParentFile() ); 101 102 OutputStream fos = null; 103 try 104 { 105 fos = new FileOutputStream( target ); 106 107 if ( data != null ) 108 { 109 fos.write( data.getBytes( "UTF-8" ) ); 110 } 111 112 // allow output to report any flush/close errors 113 fos.close(); 114 } 115 finally 116 { 117 close( fos ); 118 } 119 } 120 121 public void write( File target, InputStream source ) 122 throws IOException 123 { 124 mkdirs( target.getAbsoluteFile().getParentFile() ); 125 126 OutputStream fos = null; 127 try 128 { 129 fos = new FileOutputStream( target ); 130 131 copy( fos, source, null ); 132 133 // allow output to report any flush/close errors 134 fos.close(); 135 } 136 finally 137 { 138 close( fos ); 139 } 140 } 141 142 public void copy( File source, File target ) 143 throws IOException 144 { 145 copy( source, target, null ); 146 } 147 148 public long copy( File source, File target, ProgressListener listener ) 149 throws IOException 150 { 151 long total = 0; 152 153 InputStream fis = null; 154 OutputStream fos = null; 155 try 156 { 157 fis = new FileInputStream( source ); 158 159 mkdirs( target.getAbsoluteFile().getParentFile() ); 160 161 fos = new FileOutputStream( target ); 162 163 total = copy( fos, fis, listener ); 164 165 // allow output to report any flush/close errors 166 fos.close(); 167 } 168 finally 169 { 170 close( fis ); 171 close( fos ); 172 } 173 174 return total; 175 } 176 177 private long copy( OutputStream os, InputStream is, ProgressListener listener ) 178 throws IOException 179 { 180 long total = 0; 181 182 ByteBuffer buffer = ByteBuffer.allocate( 1024 * 32 ); 183 byte[] array = buffer.array(); 184 185 while ( true ) 186 { 187 int bytes = is.read( array ); 188 if ( bytes < 0 ) 189 { 190 break; 191 } 192 193 os.write( array, 0, bytes ); 194 195 total += bytes; 196 197 if ( listener != null && bytes > 0 ) 198 { 199 try 200 { 201 buffer.rewind(); 202 buffer.limit( bytes ); 203 listener.progressed( buffer ); 204 } 205 catch ( Exception e ) 206 { 207 // too bad 208 } 209 } 210 } 211 212 return total; 213 } 214 215 public void move( File source, File target ) 216 throws IOException 217 { 218 if ( !source.renameTo( target ) ) 219 { 220 copy( source, target ); 221 222 target.setLastModified( source.lastModified() ); 223 224 source.delete(); 225 } 226 } 227 228}