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.ByteBuffer;
29  import java.nio.charset.StandardCharsets;
30  
31  import javax.inject.Named;
32  import javax.inject.Singleton;
33  
34  import org.eclipse.aether.spi.io.FileProcessor;
35  import org.eclipse.aether.util.ChecksumUtils;
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         byte[] buffer = new byte[ 1024 * 32 ];
216         while ( true )
217         {
218             int bytes = is.read( buffer );
219             if ( bytes < 0 )
220             {
221                 break;
222             }
223 
224             os.write( buffer, 0, bytes );
225 
226             total += bytes;
227 
228             if ( listener != null && bytes > 0 )
229             {
230                 try
231                 {
232                     listener.progressed( ByteBuffer.wrap( buffer, 0, bytes ) );
233                 }
234                 catch ( Exception e )
235                 {
236                     // too bad
237                 }
238             }
239         }
240 
241         return total;
242     }
243 
244     public void move( File source, File target )
245         throws IOException
246     {
247         if ( !source.renameTo( target ) )
248         {
249             copy( source, target );
250 
251             target.setLastModified( source.lastModified() );
252 
253             source.delete();
254         }
255     }
256 
257     @Override
258     public String readChecksum( final File checksumFile ) throws IOException
259     {
260         // for now do exactly same as happened before, but FileProcessor is a component and can be replaced
261         return ChecksumUtils.read( checksumFile );
262     }
263 
264     @Override
265     public void writeChecksum( final File checksumFile, final String checksum ) throws IOException
266     {
267         // for now do exactly same as happened before, but FileProcessor is a component and can be replaced
268         write( checksumFile, checksum );
269     }
270 }