Reworked configuration and the tracking thereof
[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
37   private final File saved;
38   private final MessageDigest digest;
39   private final Log log;
40
41
42   ModificationTracker(String buildDirectory, String filename, Log log)
43       throws
44         NoSuchAlgorithmException
45   {
46     propertyNames = new HashSet<String>();
47     classNames = new HashSet<String>();
48     File output = new File(filename + ".md5s");
49     if (output.isAbsolute())
50     {
51       saved = output;
52     }
53     else
54     {
55       // Interpret relative file path relative to build directory
56       saved = new File(buildDirectory, output.getPath());
57       log.debug("Adjusted relative path, resulting path is " + saved.getPath());
58     }
59     digest = java.security.MessageDigest.getInstance("MD5");
60     this.log = log;
61   }
62
63
64   private String calculate(InputStream is)
65       throws
66         IOException
67   {
68     byte[] buffer = new byte[1024*4]; // copy data in 4MB-chunks
69     int i;
70     while((i = is.read(buffer)) > -1)
71       digest.update(buffer, 0, i);
72     is.close();
73     byte[] bytes = digest.digest();
74     BigInteger bi = new BigInteger(1, bytes);
75     return String.format("%0" + (bytes.length << 1) + "x", bi);
76   }
77
78   private boolean check(Map<String,String> values, String name, String value)
79   {
80     if (!values.containsKey(name) || !values.get(name).equals(value))
81     {
82       values.put(name, value);
83       return true;
84     }
85     else
86       return false;
87   }
88
89
90   boolean track(String name, InputStream is) throws IOException
91   {
92     boolean result = check(classes, name, calculate(is));
93     classNames.add(name);
94     modified |= result;
95     return result;
96   }
97
98
99   boolean check(String name, String property)
100   {
101     propertyNames.add(name);
102     return check(properties, name, property);
103   }
104
105   boolean track(String name, String property)
106   {
107     boolean result = check(name, property);
108     modified |= result;
109     return result;
110   }
111
112   boolean track(Properties properties)
113   {
114     boolean result = false;
115     for (String name : properties.stringPropertyNames())
116       result |= track(name, properties.getProperty(name));
117     return result;
118   }
119
120
121   void touch()
122   {
123     modified = true;
124   }
125
126   boolean modified()
127   {
128     modified |= !propertyNames.containsAll(properties.keySet());
129     modified |= !properties.keySet().containsAll(propertyNames);
130     modified |= !classNames.containsAll(classes.keySet());
131     modified |= !classes.keySet().containsAll(classNames);
132     return modified;
133   }
134
135
136   void load()
137   {
138     if (saved.isFile() && saved.length() > 0)
139     {
140       try
141       {
142         FileInputStream fis = new FileInputStream(saved);
143         ObjectInputStream ois = new ObjectInputStream(fis);
144         properties = (HashMap<String,String>)ois.readObject();
145         classes = (HashMap<String,String>)ois.readObject();
146         ois.close();
147       }
148       catch (Exception e)
149       {
150         properties = new HashMap<String,String>();
151         classes = new HashMap<String,String>();
152         log.warn("Cannot read md5s from saved: " + e);
153       }
154     }
155     else
156     {
157       properties = new HashMap<String,String>();
158       classes = new HashMap<String,String>();
159       try
160       {
161         saved.createNewFile();
162       }
163       catch (IOException e)
164       {
165         log.debug("Cannot create file \"" + saved.getPath() + "\" for md5s: " + e);
166       }
167     }
168   }
169
170   void save()
171   {
172     if (!modified)
173       return;
174
175     /** Write md5-sums for annotated classes to file */
176     try
177     {
178       FileOutputStream fos = new FileOutputStream(saved);
179       ObjectOutputStream oos = new ObjectOutputStream(fos);
180       oos.writeObject(properties);
181       oos.writeObject(classes);
182       oos.close();
183       fos.close();
184     }
185     catch (Exception e)
186     {
187       log.error("Cannot write md5-sums to file: " + e);
188     }
189   }  
190 }