d9ce624d03a7efc53a8e78de471720d7180e99bc
[hibernate4-maven-plugin] / src / main / java / de / juplo / plugins / hibernate / ModificationTracker.java
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  * @author Kai Moritz
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       // Interpret relative file path relative to build directory
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]; // copy data in 4MB-chunks
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     modified |= !propertyNames.containsAll(properties.keySet());
130     modified |= !properties.keySet().containsAll(propertyNames);
131     modified |= !classNames.containsAll(classes.keySet());
132     modified |= !classes.keySet().containsAll(classNames);
133     return modified;
134   }
135
136
137   void failed()
138   {
139     failed = true;
140   }
141
142
143   void load()
144   {
145     if (saved.isFile() && saved.length() > 0)
146     {
147       try
148       {
149         FileInputStream fis = new FileInputStream(saved);
150         ObjectInputStream ois = new ObjectInputStream(fis);
151         properties = (HashMap<String,String>)ois.readObject();
152         classes = (HashMap<String,String>)ois.readObject();
153         ois.close();
154       }
155       catch (Exception e)
156       {
157         properties = new HashMap<String,String>();
158         classes = new HashMap<String,String>();
159         log.warn("Cannot read md5s from saved: " + e);
160       }
161     }
162     else
163     {
164       properties = new HashMap<String,String>();
165       classes = new HashMap<String,String>();
166       try
167       {
168         saved.createNewFile();
169       }
170       catch (IOException e)
171       {
172         log.debug("Cannot create file \"" + saved.getPath() + "\" for md5s: " + e);
173       }
174     }
175   }
176
177   void save()
178   {
179     if (failed)
180     {
181       saved.delete();
182       return;
183     }
184
185     if (!modified)
186       return;
187
188     /** Write md5-sums for annotated classes to file */
189     try
190     {
191       FileOutputStream fos = new FileOutputStream(saved);
192       ObjectOutputStream oos = new ObjectOutputStream(fos);
193       oos.writeObject(properties);
194       oos.writeObject(classes);
195       oos.close();
196       fos.close();
197     }
198     catch (Exception e)
199     {
200       log.error("Cannot write md5-sums to file: " + e);
201     }
202   }  
203 }