1
18 package net.bull.javamelody.internal.model;
19
20 import java.io.File;
21 import java.io.FileInputStream;
22 import java.io.FileOutputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.OutputStream;
26 import java.io.Serializable;
27 import java.text.ParseException;
28 import java.text.SimpleDateFormat;
29 import java.util.ArrayList;
30 import java.util.Collections;
31 import java.util.Comparator;
32 import java.util.Date;
33 import java.util.HashMap;
34 import java.util.LinkedHashMap;
35 import java.util.List;
36 import java.util.Locale;
37 import java.util.Map;
38 import java.util.Properties;
39
40 import net.bull.javamelody.internal.common.LOG;
41 import net.bull.javamelody.internal.common.Parameters;
42
43
47 class WebappVersions {
48 private static final Comparator<Map.Entry<String, Date>> WEBAPP_VERSIONS_VALUE_COMPARATOR = Collections
49 .reverseOrder(new MapValueComparator<String, Date>());
50 private static final String VERSIONS_FILENAME = "versions.properties";
51 private static final String VERSIONS_DATE_PATTERN = "yyyy/MM/dd";
52
53
56 private final Map<String, Date> datesByVersions;
57 private final File versionsFile;
58
59 private static class MapValueComparator<K, V extends Comparable<V>>
60 implements Comparator<Map.Entry<K, V>>, Serializable {
61 private static final long serialVersionUID = 1L;
62
63 MapValueComparator() {
64 super();
65 }
66
67 @Override
68 public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
69 return o1.getValue().compareTo(o2.getValue());
70 }
71 }
72
73 WebappVersions(String application) {
74 super();
75 assert application != null;
76 final File storageDirectory = Parameters.getStorageDirectory(application);
77 this.versionsFile = new File(storageDirectory, VERSIONS_FILENAME);
78 this.datesByVersions = readDatesByVersions();
79 }
80
81 @SuppressWarnings("unchecked")
82 private Map<String, Date> readDatesByVersions() {
83 final Map<String, Date> result = new HashMap<>();
84 if (versionsFile.exists()) {
85 final Properties versionsProperties = new Properties();
86 try {
87 try (InputStream input = new FileInputStream(versionsFile)) {
88 versionsProperties.load(input);
89 }
90 final List<String> propertyNames = (List<String>) Collections
91 .list(versionsProperties.propertyNames());
92 final SimpleDateFormat dateFormat = new SimpleDateFormat(VERSIONS_DATE_PATTERN,
93 Locale.US);
94 for (final String version : propertyNames) {
95 try {
96 final Date date = dateFormat.parse(versionsProperties.getProperty(version));
97 result.put(version, date);
98 } catch (final ParseException e) {
99 continue;
100 }
101 }
102 } catch (final IOException e) {
103
104 LOG.warn("exception while reading versions in " + versionsFile, e);
105 }
106 }
107 return result;
108 }
109
110 Map<String, Date> getDatesByVersions() {
111 final List<Map.Entry<String, Date>> entries = new ArrayList<>(datesByVersions.entrySet());
112 Collections.sort(entries, WEBAPP_VERSIONS_VALUE_COMPARATOR);
113 final Map<String, Date> map = new LinkedHashMap<>();
114 for (final Map.Entry<String, Date> entry : entries) {
115 map.put(entry.getKey(), entry.getValue());
116 }
117 return Collections.unmodifiableMap(map);
118 }
119
120 void addVersionIfNeeded(String webappVersion) throws IOException {
121 if (webappVersion == null || datesByVersions.containsKey(webappVersion)) {
122 return;
123 }
124
125 final Properties versionsProperties = new Properties();
126 if (versionsFile.exists()) {
127 try (InputStream input = new FileInputStream(versionsFile)) {
128 versionsProperties.load(input);
129 }
130 }
131 assert versionsProperties.getProperty(webappVersion) == null;
132
133 final SimpleDateFormat dateFormat = new SimpleDateFormat(VERSIONS_DATE_PATTERN, Locale.US);
134 versionsProperties.setProperty(webappVersion, dateFormat.format(new Date()));
135
136 final File directory = versionsFile.getParentFile();
137 if (!directory.mkdirs() && !directory.exists()) {
138 throw new IOException("JavaMelody directory can't be created: " + directory.getPath());
139 }
140 try (OutputStream output = new FileOutputStream(versionsFile)) {
141 versionsProperties.store(output, "Application deployments with versions and dates");
142 }
143 datesByVersions.put(webappVersion, new Date());
144 LOG.debug("New application version added: " + webappVersion);
145 }
146 }
147