1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.transport.file;
20
21 import java.nio.ByteBuffer;
22 import java.nio.channels.FileChannel;
23 import java.nio.file.Files;
24 import java.nio.file.Path;
25
26 import org.eclipse.aether.spi.connector.transport.AbstractTransporter;
27 import org.eclipse.aether.spi.connector.transport.GetTask;
28 import org.eclipse.aether.spi.connector.transport.PeekTask;
29 import org.eclipse.aether.spi.connector.transport.PutTask;
30 import org.eclipse.aether.spi.connector.transport.TransportTask;
31 import org.eclipse.aether.transfer.NoTransporterException;
32
33
34
35
36 final class FileTransporter extends AbstractTransporter {
37
38
39
40
41
42 enum FileOp {
43 COPY,
44 SYMLINK,
45 HARDLINK;
46 }
47
48 private final Path basePath;
49 private final FileOp fileOp;
50
51 FileTransporter(Path basePath, FileOp fileOp) throws NoTransporterException {
52 this.basePath = basePath;
53 this.fileOp = fileOp;
54 }
55
56 Path getBasePath() {
57 return basePath;
58 }
59
60 @Override
61 public int classify(Throwable error) {
62 if (error instanceof ResourceNotFoundException) {
63 return ERROR_NOT_FOUND;
64 }
65 return ERROR_OTHER;
66 }
67
68 private FileOp effectiveFileOp(FileOp wanted, GetTask task) {
69 if (task.getDataPath() != null) {
70 return wanted;
71 }
72
73 return FileOp.COPY;
74 }
75
76 @Override
77 protected void implPeek(PeekTask task) throws Exception {
78 getPath(task, true);
79 }
80
81 @Override
82 protected void implGet(GetTask task) throws Exception {
83 Path path = getPath(task, true);
84 long size = Files.size(path);
85 FileOp effective = effectiveFileOp(fileOp, task);
86 switch (effective) {
87 case COPY:
88 utilGet(task, Files.newInputStream(path), true, size, false);
89 break;
90 case SYMLINK:
91 case HARDLINK:
92 Files.deleteIfExists(task.getDataPath());
93 task.getListener().transportStarted(0L, size);
94 if (effective == FileOp.HARDLINK) {
95 Files.createLink(task.getDataPath(), path);
96 } else {
97 Files.createSymbolicLink(task.getDataPath(), path);
98 }
99 if (size > 0) {
100 try (FileChannel fc = FileChannel.open(path)) {
101 try {
102 task.getListener().transportProgressed(fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()));
103 } catch (UnsupportedOperationException e) {
104
105 ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 32);
106 while (fc.read(byteBuffer) != -1) {
107 byteBuffer.flip();
108 task.getListener().transportProgressed(byteBuffer);
109 byteBuffer.clear();
110 }
111 }
112 }
113 }
114 break;
115 default:
116 throw new IllegalStateException("Unknown fileOp" + fileOp);
117 }
118 }
119
120 @Override
121 protected void implPut(PutTask task) throws Exception {
122 Path path = getPath(task, false);
123 Files.createDirectories(path.getParent());
124 try {
125 utilPut(task, Files.newOutputStream(path), true);
126 } catch (Exception e) {
127 Files.deleteIfExists(path);
128 throw e;
129 }
130 }
131
132 private Path getPath(TransportTask task, boolean required) throws Exception {
133 String path = task.getLocation().getPath();
134 if (path.contains("../")) {
135 throw new IllegalArgumentException("illegal resource path: " + path);
136 }
137 Path file = basePath.resolve(path);
138 if (required && !Files.isRegularFile(file)) {
139 throw new ResourceNotFoundException("Could not locate " + file);
140 }
141 return file;
142 }
143
144 @Override
145 protected void implClose() {}
146 }