1 package de.juplo.plugins.hibernate;
4 import static de.juplo.plugins.hibernate.AbstractSchemaMojo.SCRIPT;
6 import java.io.FileInputStream;
7 import java.io.FileOutputStream;
8 import java.io.IOException;
9 import java.io.InputStream;
10 import java.io.ObjectInputStream;
11 import java.io.ObjectOutputStream;
12 import java.math.BigInteger;
13 import java.security.MessageDigest;
14 import java.security.NoSuchAlgorithmException;
15 import java.time.ZonedDateTime;
16 import java.util.HashMap;
17 import java.util.HashSet;
19 import java.util.Properties;
21 import org.apache.maven.plugin.logging.Log;
29 public class MD5ModificationTracker implements ModificationTracker
31 private Map<String,String> properties;
32 private Map<String,String> classes;
34 private final Set<String> propertyNames;
35 private final Set<String> classNames;
37 private boolean modified = false;
38 private boolean failed = false;
40 private final File output;
41 private final File saved;
42 private final MessageDigest digest;
43 private final Log log;
46 MD5ModificationTracker(String buildDirectory, String filename, Log log)
48 NoSuchAlgorithmException
50 propertyNames = new HashSet<String>();
51 classNames = new HashSet<String>();
52 output = new File(filename);
53 File tmp = new File(filename + ".md5s");
60 // Interpret relative file path relative to build directory
61 saved = new File(buildDirectory, tmp.getPath());
62 log.debug("Adjusted relative path, resulting path is " + saved.getPath());
64 digest = java.security.MessageDigest.getInstance("MD5");
69 private String calculate(InputStream is)
73 byte[] buffer = new byte[1024*4]; // copy data in 4MB-chunks
75 while((i = is.read(buffer)) > -1)
76 digest.update(buffer, 0, i);
78 byte[] bytes = digest.digest();
79 BigInteger bi = new BigInteger(1, bytes);
80 return String.format("%0" + (bytes.length << 1) + "x", bi);
83 private boolean check(Map<String,String> values, String name, String value)
85 if (!values.containsKey(name) || !values.get(name).equals(value))
87 values.put(name, value);
96 public boolean track(String name, InputStream is) throws IOException
98 boolean result = check(classes, name, calculate(is));
105 public boolean check(String name, String property)
107 propertyNames.add(name);
108 return check(properties, name, property);
112 public boolean track(String name, String property)
114 boolean result = check(name, property);
120 public boolean track(Properties properties)
122 boolean result = false;
123 for (String name : properties.stringPropertyNames())
124 result |= track(name, properties.getProperty(name));
129 public void track() throws IOException
132 track(SCRIPT, new FileInputStream(output));
134 track(SCRIPT, ZonedDateTime.now().toString());
145 public boolean modified()
147 for (String property : new HashSet<String>(properties.keySet()))
148 if (!propertyNames.contains(property))
151 properties.remove(property);
153 for (String clazz : new HashSet<String>(classes.keySet()))
154 if (!classNames.contains(clazz))
157 classes.remove(clazz);
173 if (saved.isFile() && saved.length() > 0)
177 FileInputStream fis = new FileInputStream(saved);
178 ObjectInputStream ois = new ObjectInputStream(fis);
179 properties = (HashMap<String,String>)ois.readObject();
180 classes = (HashMap<String,String>)ois.readObject();
185 properties = new HashMap<String,String>();
186 classes = new HashMap<String,String>();
187 log.warn("Cannot read md5s from saved: " + e);
192 properties = new HashMap<String,String>();
193 classes = new HashMap<String,String>();
196 saved.createNewFile();
198 catch (IOException e)
200 log.debug("Cannot create file \"" + saved.getPath() + "\" for md5s: " + e);
217 /** Write md5-sums for annotated classes to file */
220 FileOutputStream fos = new FileOutputStream(saved);
221 ObjectOutputStream oos = new ObjectOutputStream(fos);
222 oos.writeObject(properties);
223 oos.writeObject(classes);
229 log.error("Cannot write md5-sums to file: " + e);
235 public void turncat() throws IOException
237 new FileOutputStream(output).getChannel().truncate(0).close();