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 public Resource locate(final String name) {
51 if (notFoundResources.contains(name)) {
52 return NOT_EXISTING_RESOURCE;
53 } else {
54 return new CachingResource(name);
55 }
56 }
57
58 private class CachingResource implements Resource {
59 private final String name;
60
61 private CachingResource(final String name) {
62 this.name = name;
63 }
64
65 public InputStream read() throws IOException {
66 InputStream inputStream = local.locate(name).read();
67 if (inputStream != null) {
68 return inputStream;
69 }
70 if (cacheLocally(name)) {
71 return local.locate(name).read();
72 }
73 notFoundResources.add(name);
74 return null;
75 }
76
77 private boolean cacheLocally(final String name) throws IOException {
78 final Resource remoteResource = remote.locate(name);
79 try (WritableResource localResource = local.locate(name);
80 final InputStream inputStream = remoteResource.read();
81 final OutputStream outputStream = localResource.write()) {
82 if (inputStream != null) {
83 int read;
84 byte[] bytes = new byte[8192];
85 while ((read = inputStream.read(bytes)) != -1) {
86 outputStream.write(bytes, 0, read);
87 }
88 outputStream.flush();
89 return true;
90 }
91 return false;
92 }
93 }
94 }
95
96 public void close() throws IOException {
97 remote.close();
98 local.close();
99 }
100 }