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.*;
25  import java.nio.ByteBuffer;
26  import java.nio.charset.StandardCharsets;
27  import java.nio.file.Files;
28  import java.nio.file.StandardCopyOption;
29  
30  import org.eclipse.aether.spi.io.FileProcessor;
31  import org.eclipse.aether.util.FileUtils;
32  
33  /**
34   * A utility class helping with file-based operations.
35   *
36   * @deprecated
37   */
38  @Deprecated
39  @Singleton
40  @Named
41  public class DefaultFileProcessor implements FileProcessor {
42  
43      /**
44       * Thread-safe variant of {@link File#mkdirs()}. Creates the directory named by the given abstract pathname,
45       * including any necessary but nonexistent parent directories. Note that if this operation fails it may have
46       * succeeded in creating some of the necessary parent directories.
47       *
48       * @param directory The directory to create, may be {@code null}.
49       * @return {@code true} if and only if the directory was created, along with all necessary parent directories;
50       * {@code false} otherwise
51       */
52      @Override
53      public boolean mkdirs(File directory) {
54          if (directory == null) {
55              return false;
56          }
57  
58          if (directory.exists()) {
59              return false;
60          }
61          if (directory.mkdir()) {
62              return true;
63          }
64  
65          File canonDir;
66          try {
67              canonDir = directory.getCanonicalFile();
68          } catch (IOException e) {
69              throw new UncheckedIOException(e);
70          }
71  
72          File parentDir = canonDir.getParentFile();
73          return (parentDir != null && (mkdirs(parentDir) || parentDir.exists()) && canonDir.mkdir());
74      }
75  
76      @Override
77      public void write(File target, String data) throws IOException {
78          FileUtils.writeFile(target.toPath(), p -> Files.write(p, data.getBytes(StandardCharsets.UTF_8)));
79      }
80  
81      @Override
82      public void write(File target, InputStream source) throws IOException {
83          FileUtils.writeFile(target.toPath(), p -> Files.copy(source, p, StandardCopyOption.REPLACE_EXISTING));
84      }
85  
86      @Override
87      public void copy(File source, File target) throws IOException {
88          copy(source, target, null);
89      }
90  
91      @Override
92      public long copy(File source, File target, ProgressListener listener) throws IOException {
93          try (InputStream in = new BufferedInputStream(Files.newInputStream(source.toPath()));
94                  FileUtils.CollocatedTempFile tempTarget = FileUtils.newTempFile(target.toPath());
95                  OutputStream out = new BufferedOutputStream(Files.newOutputStream(tempTarget.getPath()))) {
96              long result = copy(out, in, listener);
97              tempTarget.move();
98              return result;
99          }
100     }
101 
102     private long copy(OutputStream os, InputStream is, ProgressListener listener) throws IOException {
103         long total = 0L;
104         byte[] buffer = new byte[1024 * 32];
105         while (true) {
106             int bytes = is.read(buffer);
107             if (bytes < 0) {
108                 break;
109             }
110 
111             os.write(buffer, 0, bytes);
112 
113             total += bytes;
114 
115             if (listener != null && bytes > 0) {
116                 try {
117                     listener.progressed(ByteBuffer.wrap(buffer, 0, bytes));
118                 } catch (Exception e) {
119                     // too bad
120                 }
121             }
122         }
123 
124         return total;
125     }
126 
127     @Override
128     public void move(File source, File target) throws IOException {
129         if (!source.renameTo(target)) {
130             copy(source, target);
131 
132             target.setLastModified(source.lastModified());
133 
134             source.delete();
135         }
136     }
137 
138     @Override
139     public String readChecksum(final File checksumFile) throws IOException {
140         // for now do exactly same as happened before, but FileProcessor is a component and can be replaced
141         String checksum = "";
142         try (BufferedReader br = new BufferedReader(
143                 new InputStreamReader(Files.newInputStream(checksumFile.toPath()), StandardCharsets.UTF_8), 512)) {
144             while (true) {
145                 String line = br.readLine();
146                 if (line == null) {
147                     break;
148                 }
149                 line = line.trim();
150                 if (!line.isEmpty()) {
151                     checksum = line;
152                     break;
153                 }
154             }
155         }
156 
157         if (checksum.matches(".+= [0-9A-Fa-f]+")) {
158             int lastSpacePos = checksum.lastIndexOf(' ');
159             checksum = checksum.substring(lastSpacePos + 1);
160         } else {
161             int spacePos = checksum.indexOf(' ');
162 
163             if (spacePos != -1) {
164                 checksum = checksum.substring(0, spacePos);
165             }
166         }
167 
168         return checksum;
169     }
170 
171     @Override
172     public void writeChecksum(final File checksumFile, final String checksum) throws IOException {
173         // for now do exactly same as happened before, but FileProcessor is a component and can be replaced
174         write(checksumFile, checksum);
175     }
176 }