1 package de.juplo.plugins.hibernate;
2
3
4 import java.io.File;
5 import java.io.FileInputStream;
6 import java.io.FileOutputStream;
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.io.ObjectInputStream;
10 import java.io.ObjectOutputStream;
11 import java.math.BigInteger;
12 import java.security.MessageDigest;
13 import java.security.NoSuchAlgorithmException;
14 import java.util.HashMap;
15 import java.util.HashSet;
16 import java.util.Map;
17 import java.util.Properties;
18 import java.util.Set;
19 import org.apache.maven.plugin.logging.Log;
20
21
22
23
24
25
26
27 public class ModificationTracker
28 {
29 private Map<String,String> properties;
30 private Map<String,String> classes;
31
32 private final Set<String> propertyNames;
33 private final Set<String> classNames;
34
35 private boolean modified = false;
36 private boolean failed = false;
37
38 private final File saved;
39 private final MessageDigest digest;
40 private final Log log;
41
42
43 ModificationTracker(String buildDirectory, String filename, Log log)
44 throws
45 NoSuchAlgorithmException
46 {
47 propertyNames = new HashSet<String>();
48 classNames = new HashSet<String>();
49 File output = new File(filename + ".md5s");
50 if (output.isAbsolute())
51 {
52 saved = output;
53 }
54 else
55 {
56
57 saved = new File(buildDirectory, output.getPath());
58 log.debug("Adjusted relative path, resulting path is " + saved.getPath());
59 }
60 digest = java.security.MessageDigest.getInstance("MD5");
61 this.log = log;
62 }
63
64
65 private String calculate(InputStream is)
66 throws
67 IOException
68 {
69 byte[] buffer = new byte[1024*4];
70 int i;
71 while((i = is.read(buffer)) > -1)
72 digest.update(buffer, 0, i);
73 is.close();
74 byte[] bytes = digest.digest();
75 BigInteger bi = new BigInteger(1, bytes);
76 return String.format("%0" + (bytes.length << 1) + "x", bi);
77 }
78
79 private boolean check(Map<String,String> values, String name, String value)
80 {
81 if (!values.containsKey(name) || !values.get(name).equals(value))
82 {
83 values.put(name, value);
84 return true;
85 }
86 else
87 return false;
88 }
89
90
91 boolean track(String name, InputStream is) throws IOException
92 {
93 boolean result = check(classes, name, calculate(is));
94 classNames.add(name);
95 modified |= result;
96 return result;
97 }
98
99
100 boolean check(String name, String property)
101 {
102 propertyNames.add(name);
103 return check(properties, name, property);
104 }
105
106 boolean track(String name, String property)
107 {
108 boolean result = check(name, property);
109 modified |= result;
110 return result;
111 }
112
113 boolean track(Properties properties)
114 {
115 boolean result = false;
116 for (String name : properties.stringPropertyNames())
117 result |= track(name, properties.getProperty(name));
118 return result;
119 }
120
121
122 void touch()
123 {
124 modified = true;
125 }
126
127 boolean modified()
128 {
129 for (String property : new HashSet<String>(properties.keySet()))
130 if (!propertyNames.contains(property))
131 {
132 modified = true;
133 properties.remove(property);
134 }
135 for (String clazz : new HashSet<String>(classes.keySet()))
136 if (!classNames.contains(clazz))
137 {
138 modified = true;
139 classes.remove(clazz);
140 }
141 return modified;
142 }
143
144
145 void failed()
146 {
147 failed = true;
148 }
149
150
151 void load()
152 {
153 if (saved.isFile() && saved.length() > 0)
154 {
155 try
156 {
157 FileInputStream fis = new FileInputStream(saved);
158 ObjectInputStream ois = new ObjectInputStream(fis);
159 properties = (HashMap<String,String>)ois.readObject();
160 classes = (HashMap<String,String>)ois.readObject();
161 ois.close();
162 }
163 catch (Exception e)
164 {
165 properties = new HashMap<String,String>();
166 classes = new HashMap<String,String>();
167 log.warn("Cannot read md5s from saved: " + e);
168 }
169 }
170 else
171 {
172 properties = new HashMap<String,String>();
173 classes = new HashMap<String,String>();
174 try
175 {
176 saved.createNewFile();
177 }
178 catch (IOException e)
179 {
180 log.debug("Cannot create file \"" + saved.getPath() + "\" for md5s: " + e);
181 }
182 }
183 }
184
185 void save()
186 {
187 if (failed)
188 {
189 saved.delete();
190 return;
191 }
192
193 if (!modified)
194 return;
195
196
197 try
198 {
199 FileOutputStream fos = new FileOutputStream(saved);
200 ObjectOutputStream oos = new ObjectOutputStream(fos);
201 oos.writeObject(properties);
202 oos.writeObject(classes);
203 oos.close();
204 fos.close();
205 }
206 catch (Exception e)
207 {
208 log.error("Cannot write md5-sums to file: " + e);
209 }
210 }
211 }