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.Closeable;
23  import java.io.File;
24  import java.io.FileInputStream;
25  import java.io.FileOutputStream;
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.io.OutputStream;
29  import java.nio.ByteBuffer;
30  
31  import javax.inject.Named;
32  
33  import org.eclipse.aether.spi.io.FileProcessor;
34  
35  /**
36   * A utility class helping with file-based operations.
37   */
38  @Named
39  public class DefaultFileProcessor
40      implements FileProcessor
41  {
42  
43      private static void close( Closeable closeable )
44      {
45          if ( closeable != null )
46          {
47              try
48              {
49                  closeable.close();
50              }
51              catch ( IOException e )
52              {
53                  // too bad but who cares
54              }
55          }
56      }
57  
58      /**
59       * Thread-safe variant of {@link File#mkdirs()}. Creates the directory named by the given abstract pathname,
60       * including any necessary but nonexistent parent directories. Note that if this operation fails it may have
61       * succeeded in creating some of the necessary parent directories.
62       * 
63       * @param directory The directory to create, may be {@code null}.
64       * @return {@code true} if and only if the directory was created, along with all necessary parent directories;
65       *         {@code false} otherwise
66       */
67      public boolean mkdirs( File directory )
68      {
69          if ( directory == null )
70          {
71              return false;
72          }
73  
74          if ( directory.exists() )
75          {
76              return false;
77          }
78          if ( directory.mkdir() )
79          {
80              return true;
81          }
82  
83          File canonDir;
84          try
85          {
86              canonDir = directory.getCanonicalFile();
87          }
88          catch ( IOException e )
89          {
90              return false;
91          }
92  
93          File parentDir = canonDir.getParentFile();
94          return ( parentDir != null && ( mkdirs( parentDir ) || parentDir.exists() ) && canonDir.mkdir() );
95      }
96  
97      public void write( File target, String data )
98          throws IOException
99      {
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 }