X-Git-Url: http://juplo.de/gitweb/?p=hibernate4-maven-plugin;a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fde%2Fjuplo%2Fplugins%2Fhibernate%2FMD5ModificationTracker.java;fp=src%2Fmain%2Fjava%2Fde%2Fjuplo%2Fplugins%2Fhibernate%2FMD5ModificationTracker.java;h=0349906a3e784fc2ca57b250979764820d208061;hp=0000000000000000000000000000000000000000;hb=bec99c73fea6edf073dcf885ef07defee1ed8608;hpb=b0a9136540aab84ac78db6a9ada9d5da35074e16 diff --git a/src/main/java/de/juplo/plugins/hibernate/MD5ModificationTracker.java b/src/main/java/de/juplo/plugins/hibernate/MD5ModificationTracker.java new file mode 100644 index 00000000..0349906a --- /dev/null +++ b/src/main/java/de/juplo/plugins/hibernate/MD5ModificationTracker.java @@ -0,0 +1,239 @@ +package de.juplo.plugins.hibernate; + + +import static de.juplo.plugins.hibernate.AbstractSchemaMojo.SCRIPT; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.time.ZonedDateTime; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import org.apache.maven.plugin.logging.Log; + + + +/** + * + * @author Kai Moritz + */ +public class MD5ModificationTracker implements ModificationTracker +{ + private Map properties; + private Map classes; + + private final Set propertyNames; + private final Set classNames; + + private boolean modified = false; + private boolean failed = false; + + private final File output; + private final File saved; + private final MessageDigest digest; + private final Log log; + + + MD5ModificationTracker(String buildDirectory, String filename, Log log) + throws + NoSuchAlgorithmException + { + propertyNames = new HashSet(); + classNames = new HashSet(); + output = new File(filename); + File tmp = new File(filename + ".md5s"); + if (tmp.isAbsolute()) + { + saved = tmp; + } + else + { + // Interpret relative file path relative to build directory + saved = new File(buildDirectory, tmp.getPath()); + log.debug("Adjusted relative path, resulting path is " + saved.getPath()); + } + digest = java.security.MessageDigest.getInstance("MD5"); + this.log = log; + } + + + private String calculate(InputStream is) + throws + IOException + { + byte[] buffer = new byte[1024*4]; // copy data in 4MB-chunks + int i; + while((i = is.read(buffer)) > -1) + digest.update(buffer, 0, i); + is.close(); + byte[] bytes = digest.digest(); + BigInteger bi = new BigInteger(1, bytes); + return String.format("%0" + (bytes.length << 1) + "x", bi); + } + + private boolean check(Map values, String name, String value) + { + if (!values.containsKey(name) || !values.get(name).equals(value)) + { + values.put(name, value); + return true; + } + else + return false; + } + + + @Override + public boolean track(String name, InputStream is) throws IOException + { + boolean result = check(classes, name, calculate(is)); + classNames.add(name); + modified |= result; + return result; + } + + @Override + public boolean check(String name, String property) + { + propertyNames.add(name); + return check(properties, name, property); + } + + @Override + public boolean track(String name, String property) + { + boolean result = check(name, property); + modified |= result; + return result; + } + + @Override + public boolean track(Properties properties) + { + boolean result = false; + for (String name : properties.stringPropertyNames()) + result |= track(name, properties.getProperty(name)); + return result; + } + + @Override + public void track() throws IOException + { + if (output.exists()) + track(SCRIPT, new FileInputStream(output)); + else + track(SCRIPT, ZonedDateTime.now().toString()); + } + + + @Override + public void touch() + { + modified = true; + } + + @Override + public boolean modified() + { + for (String property : new HashSet(properties.keySet())) + if (!propertyNames.contains(property)) + { + modified = true; + properties.remove(property); + } + for (String clazz : new HashSet(classes.keySet())) + if (!classNames.contains(clazz)) + { + modified = true; + classes.remove(clazz); + } + return modified; + } + + + @Override + public void failed() + { + failed = true; + } + + + @Override + public void load() + { + if (saved.isFile() && saved.length() > 0) + { + try + { + FileInputStream fis = new FileInputStream(saved); + ObjectInputStream ois = new ObjectInputStream(fis); + properties = (HashMap)ois.readObject(); + classes = (HashMap)ois.readObject(); + ois.close(); + } + catch (Exception e) + { + properties = new HashMap(); + classes = new HashMap(); + log.warn("Cannot read md5s from saved: " + e); + } + } + else + { + properties = new HashMap(); + classes = new HashMap(); + try + { + saved.createNewFile(); + } + catch (IOException e) + { + log.debug("Cannot create file \"" + saved.getPath() + "\" for md5s: " + e); + } + } + } + + @Override + public void save() + { + if (failed) + { + saved.delete(); + return; + } + + if (!modified) + return; + + /** Write md5-sums for annotated classes to file */ + try + { + FileOutputStream fos = new FileOutputStream(saved); + ObjectOutputStream oos = new ObjectOutputStream(fos); + oos.writeObject(properties); + oos.writeObject(classes); + oos.close(); + fos.close(); + } + catch (Exception e) + { + log.error("Cannot write md5-sums to file: " + e); + } + } + + + @Override + public void turncat() throws IOException + { + new FileOutputStream(output).getChannel().truncate(0).close(); + } +}