View Javadoc
1   package org.eclipse.aether.internal.impl;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.io.FileInputStream;
24  import java.io.FileOutputStream;
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.io.OutputStream;
28  import java.nio.Buffer;
29  import java.nio.ByteBuffer;
30  import java.nio.charset.StandardCharsets;
31  
32  import javax.inject.Named;
33  import javax.inject.Singleton;
34  
35  import org.eclipse.aether.spi.io.FileProcessor;
36  
37  /**
38   * A utility class helping with file-based operations.
39   */
40  @Singleton
41  @Named
42  public class DefaultFileProcessor
43      implements FileProcessor
44  {
45  
46      /**
47       * Thread-safe variant of {@link File#mkdirs()}. Creates the directory named by the given abstract pathname,
48       * including any necessary but nonexistent parent directories. Note that if this operation fails it may have
49       * succeeded in creating some of the necessary parent directories.
50       *
51       * @param directory The directory to create, may be {@code null}.
52       * @return {@code true} if and only if the directory was created, along with all necessary parent directories;
53       *         {@code false} otherwise
54       */
55      public boolean mkdirs( File directory )
56      {
57          if ( directory == null )
58          {
59              return false;
60          }
61  
62          if ( directory.exists() )
63          {
64              return false;
65          }
66          if ( directory.mkdir() )
67          {
68              return true;
69          }
70  
71          File canonDir;
72          try
73          {
74              canonDir = directory.getCanonicalFile();
75          }
76          catch ( IOException e )
77          {
78              return false;
79          }
80  
81          File parentDir = canonDir.getParentFile();
82          return ( parentDir != null && ( mkdirs( parentDir ) || parentDir.exists() ) && canonDir.mkdir() );
83      }
84  
85      public void write( File target, String data )
86          throws IOException
87      {
88          mkdirs( target.getAbsoluteFile().getParentFile() );
89  
90          OutputStream out = null;
91          try
92          {
93              out = new FileOutputStream( target );
94  
95              if ( data != null )
96              {
97                  out.write( data.getBytes( StandardCharsets.UTF_8 ) );
98              }
99  
100             out.close();
101             out = null;
102         }
103         finally
104         {
105             try
106             {
107                 if ( out != null )
108                 {
109                     out.close();
110                 }
111             }
112             catch ( final IOException e )
113             {
114                 // Suppressed due to an exception already thrown in the try block.
115             }
116         }
117     }
118 
119     public void write( File target, InputStream source )
120         throws IOException
121     {
122         mkdirs( target.getAbsoluteFile().getParentFile() );
123 
124         OutputStream out = null;
125         try
126         {
127             out = new FileOutputStream( target );
128 
129             copy( out, source, null );
130 
131             out.close();
132             out = null;
133         }
134         finally
135         {
136             try
137             {
138                 if ( out != null )
139                 {
140                     out.close();
141                 }
142             }
143             catch ( final IOException e )
144             {
145                 // Suppressed due to an exception already thrown in the try block.
146             }
147         }
148     }
149 
150     public void copy( File source, File target )
151         throws IOException
152     {
153         copy( source, target, null );
154     }
155 
156     public long copy( File source, File target, ProgressListener listener )
157         throws IOException
158     {
159         long total = 0L;
160 
161         InputStream in = null;
162         OutputStream out = null;
163         try
164         {
165             in = new FileInputStream( source );
166 
167             mkdirs( target.getAbsoluteFile().getParentFile() );
168 
169             out = new FileOutputStream( target );
170 
171             total = copy( out, in, listener );
172 
173             out.close();
174             out = null;
175 
176             in.close();
177             in = null;
178         }
179         finally
180         {
181             try
182             {
183                 if ( out != null )
184                 {
185                     out.close();
186                 }
187             }
188             catch ( final IOException e )
189             {
190                 // Suppressed due to an exception already thrown in the try block.
191             }
192             finally
193             {
194                 try
195                 {
196                     if ( in != null )
197                     {
198                         in.close();
199                     }
200                 }
201                 catch ( final IOException e )
202                 {
203                     // Suppressed due to an exception already thrown in the try block.
204                 }
205             }
206         }
207 
208         return total;
209     }
210 
211     private long copy( OutputStream os, InputStream is, ProgressListener listener )
212         throws IOException
213     {
214         long total = 0L;
215 
216         ByteBuffer buffer = ByteBuffer.allocate( 1024 * 32 );
217         byte[] array = buffer.array();
218 
219         while ( true )
220         {
221             int bytes = is.read( array );
222             if ( bytes < 0 )
223             {
224                 break;
225             }
226 
227             os.write( array, 0, bytes );
228 
229             total += bytes;
230 
231             if ( listener != null && bytes > 0 )
232             {
233                 try
234                 {
235                     ( (Buffer) buffer ).rewind();
236                     ( (Buffer) buffer ).limit( bytes );
237                     listener.progressed( buffer );
238                 }
239                 catch ( Exception e )
240                 {
241                     // too bad
242                 }
243             }
244         }
245 
246         return total;
247     }
248 
249     public void move( File source, File target )
250         throws IOException
251     {
252         if ( !source.renameTo( target ) )
253         {
254             copy( source, target );
255 
256             target.setLastModified( source.lastModified() );
257 
258             source.delete();
259         }
260     }
261 
262 }