1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.index.reader;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.OutputStream;
24 import java.util.HashSet;
25 import java.util.Set;
26
27 import org.apache.maven.index.reader.WritableResourceHandler.WritableResource;
28
29
30
31
32 public class CachingResourceHandler implements ResourceHandler {
33 private static final Resource NOT_EXISTING_RESOURCE = () -> null;
34
35 private final WritableResourceHandler local;
36
37 private final ResourceHandler remote;
38
39 private final Set<String> notFoundResources;
40
41 public CachingResourceHandler(final WritableResourceHandler local, final ResourceHandler remote) {
42 if (local == null || remote == null) {
43 throw new NullPointerException("null resource handler");
44 }
45 this.local = local;
46 this.remote = remote;
47 this.notFoundResources = new HashSet<>();
48 }
49
50 @Override
51 public Resource locate(final String name) {
52 if (notFoundResources.contains(name)) {
53 return NOT_EXISTING_RESOURCE;
54 } else {
55 return new CachingResource(name);
56 }
57 }
58
59 private class CachingResource implements Resource {
60 private final String name;
61
62 private CachingResource(final String name) {
63 this.name = name;
64 }
65
66 @Override
67 public InputStream read() throws IOException {
68 InputStream inputStream = local.locate(name).read();
69 if (inputStream != null) {
70 return inputStream;
71 }
72 if (cacheLocally(name)) {
73 return local.locate(name).read();
74 }
75 notFoundResources.add(name);
76 return null;
77 }
78
79 private boolean cacheLocally(final String name) throws IOException {
80 final Resource remoteResource = remote.locate(name);
81 try (WritableResource localResource = local.locate(name);
82 final InputStream inputStream = remoteResource.read();
83 final OutputStream outputStream = localResource.write()) {
84 if (inputStream != null) {
85 int read;
86 byte[] bytes = new byte[8192];
87 while ((read = inputStream.read(bytes)) != -1) {
88 outputStream.write(bytes, 0, read);
89 }
90 outputStream.flush();
91 return true;
92 }
93 return false;
94 }
95 }
96 }
97
98 @Override
99 public void close() throws IOException {
100 remote.close();
101 local.close();
102 }
103 }