View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.eclipse.aether.internal.impl;
20  
21  import javax.inject.Named;
22  import javax.inject.Singleton;
23  
24  import java.io.BufferedInputStream;
25  import java.io.BufferedOutputStream;
26  import java.io.BufferedReader;
27  import java.io.File;
28  import java.io.IOException;
29  import java.io.InputStream;
30  import java.io.InputStreamReader;
31  import java.io.OutputStream;
32  import java.io.UncheckedIOException;
33  import java.nio.ByteBuffer;
34  import java.nio.charset.StandardCharsets;
35  import java.nio.file.Files;
36  import java.nio.file.StandardCopyOption;
37  
38  import org.eclipse.aether.spi.io.FileProcessor;
39  import org.eclipse.aether.util.FileUtils;
40  
41  /**
42   * A utility class helping with file-based operations.
43   *
44   * @deprecated
45   */
46  @Deprecated
47  @Singleton
48  @Named
49  public class DefaultFileProcessor implements FileProcessor {
50  
51      /**
52       * Thread-safe variant of {@link File#mkdirs()}. Creates the directory named by the given abstract pathname,
53       * including any necessary but nonexistent parent directories. Note that if this operation fails it may have
54       * succeeded in creating some of the necessary parent directories.
55       *
56       * @param directory The directory to create, may be {@code null}.
57       * @return {@code true} if and only if the directory was created, along with all necessary parent directories;
58       * {@code false} otherwise
59       */
60      @Override
61      public boolean mkdirs(File directory) {
62          if (directory == null) {
63              return false;
64          }
65  
66          if (directory.exists()) {
67              return false;
68          }
69          if (directory.mkdir()) {
70              return true;
71          }
72  
73          File canonDir;
74          try {
75              canonDir = directory.getCanonicalFile();
76          } catch (IOException e) {
77              throw new UncheckedIOException(e);
78          }
79  
80          File parentDir = canonDir.getParentFile();
81          return (parentDir != null && (mkdirs(parentDir) || parentDir.exists()) && canonDir.mkdir());
82      }
83  
84      @Override
85      public void write(File target, String data) throws IOException {
86          FileUtils.writeFile(target.toPath(), p -> Files.write(p, data.getBytes(StandardCharsets.UTF_8)));
87      }
88  
89      @Override
90      public void write(File target, InputStream source) throws IOException {
91          FileUtils.writeFile(target.toPath(), p -> Files.copy(source, p, StandardCopyOption.REPLACE_EXISTING));
92      }
93  
94      @Override
95      public void copy(File source, File target) throws IOException {
96          copy(source, target, null);
97      }
98  
99      @Override
100     public long copy(File source, File target, ProgressListener listener) throws IOException {
101         try (InputStream in = new BufferedInputStream(Files.newInputStream(source.toPath()));
102                 FileUtils.CollocatedTempFile tempTarget = FileUtils.newTempFile(target.toPath());
103                 OutputStream out = new BufferedOutputStream(Files.newOutputStream(tempTarget.getPath()))) {
104             long result = copy(out, in, listener);
105             tempTarget.move();
106             return result;
107         }
108     }
109 
110     private long copy(OutputStream os, InputStream is, ProgressListener listener) throws IOException {
111         long total = 0L;
112         byte[] buffer = new byte[1024 * 32];
113         while (true) {
114             int bytes = is.read(buffer);
115             if (bytes < 0) {
116                 break;
117             }
118 
119             os.write(buffer, 0, bytes);
120 
121             total += bytes;
122 
123             if (listener != null && bytes > 0) {
124                 try {
125                     listener.progressed(ByteBuffer.wrap(buffer, 0, bytes));
126                 } catch (Exception e) {
127                     // too bad
128                 }
129             }
130         }
131 
132         return total;
133     }
134 
135     @Override
136     public void move(File source, File target) throws IOException {
137         if (!source.renameTo(target)) {
138             copy(source, target);
139 
140             target.setLastModified(source.lastModified());
141 
142             source.delete();
143         }
144     }
145 
146     @Override
147     public String readChecksum(final File checksumFile) throws IOException {
148         // for now do exactly same as happened before, but FileProcessor is a component and can be replaced
149         String checksum = "";
150         try (BufferedReader br = new BufferedReader(
151                 new InputStreamReader(Files.newInputStream(checksumFile.toPath()), StandardCharsets.UTF_8), 512)) {
152             while (true) {
153                 String line = br.readLine();
154                 if (line == null) {
155                     break;
156                 }
157                 line = line.trim();
158                 if (!line.isEmpty()) {
159                     checksum = line;
160                     break;
161                 }
162             }
163         }
164 
165         if (checksum.matches(".+= [0-9A-Fa-f]+")) {
166             int lastSpacePos = checksum.lastIndexOf(' ');
167             checksum = checksum.substring(lastSpacePos + 1);
168         } else {
169             int spacePos = checksum.indexOf(' ');
170 
171             if (spacePos != -1) {
172                 checksum = checksum.substring(0, spacePos);
173             }
174         }
175 
176         return checksum;
177     }
178 
179     @Override
180     public void writeChecksum(final File checksumFile, final String checksum) throws IOException {
181         // for now do exactly same as happened before, but FileProcessor is a component and can be replaced
182         write(checksumFile, checksum);
183     }
184 }