1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.owasp.dependencycheck.data.update;
19
20 import org.jspecify.annotations.NonNull;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.FileOutputStream;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.OutputStream;
30 import java.time.Duration;
31 import java.time.Instant;
32 import java.util.Properties;
33
34 import static org.owasp.dependencycheck.utils.FileUtils.existsWithContent;
35
36
37
38
39
40 public abstract class LocalDataSource implements CachedWebDataSource {
41
42
43
44
45 private static final Logger LOGGER = LoggerFactory.getLogger(LocalDataSource.class);
46
47
48
49
50
51
52 protected void saveLastUpdated(@NonNull File repo) {
53 final File timestampFile = new File(repo + ".properties");
54 try (OutputStream out = new FileOutputStream(timestampFile)) {
55 final Properties prop = new Properties();
56 prop.setProperty("LAST_UPDATED", String.valueOf(System.currentTimeMillis()));
57 prop.store(out, null);
58 } catch (IOException ex) {
59 throw new RuntimeException(ex);
60 }
61 }
62
63
64
65
66
67
68
69
70 protected Instant getLastUpdated(@NonNull File repo) {
71 long lastUpdatedOn = 0;
72 final File timestampFile = new File(repo + ".properties");
73 if (timestampFile.isFile()) {
74 try (InputStream is = new FileInputStream(timestampFile)) {
75 final Properties props = new Properties();
76 props.load(is);
77 lastUpdatedOn = Long.parseLong(props.getProperty("LAST_UPDATED", "0"));
78 } catch (IOException | NumberFormatException ex) {
79 LOGGER.debug("error reading timestamp file", ex);
80 }
81 if (lastUpdatedOn <= 0) {
82
83 lastUpdatedOn = repo.lastModified();
84 }
85 }
86 return Instant.ofEpochMilli(lastUpdatedOn);
87 }
88
89
90
91
92
93
94
95
96
97 protected boolean isStale(@NonNull File repo, @NonNull Duration validFor) {
98 boolean stale = true;
99 if (existsWithContent(repo)) {
100 final Instant lastUpdatedOn = getLastUpdated(repo);
101 final Instant now = Instant.now();
102 LOGGER.debug("{} last updated: {}, now: {}", getClass().getSimpleName(), lastUpdatedOn, now);
103 stale = lastUpdatedOn.plus(validFor).isBefore(now);
104 if (!stale) {
105 LOGGER.info("Should skip {} update since last update was within period {}.", getClass().getSimpleName(), validFor);
106 }
107 }
108 return stale;
109 }
110 }