• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  *             of Java bytecode.
4  *
5  * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu)
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the Free
9  * Software Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21 package proguard;
22 
23 import java.io.File;
24 
25 /**
26  * This class checks whether the output is up to date.
27  *
28  * @author Eric Lafortune
29  */
30 public class UpToDateChecker
31 {
32     private final Configuration configuration;
33 
34 
35     /**
36      * Creates a new UpToDateChecker with the given configuration.
37      */
UpToDateChecker(Configuration configuration)38     public UpToDateChecker(Configuration configuration)
39     {
40         this.configuration = configuration;
41     }
42 
43 
44     /**
45      * Returns whether the output is up to date, based on the modification times
46      * of the input jars, output jars, and library jars (or directories).
47      */
check()48     public boolean check()
49     {
50         try
51         {
52             ModificationTimeChecker checker = new ModificationTimeChecker();
53 
54             checker.updateInputModificationTime(configuration.lastModified);
55 
56             ClassPath programJars = configuration.programJars;
57             ClassPath libraryJars = configuration.libraryJars;
58 
59             // Check the dates of the program jars, if any.
60             if (programJars != null)
61             {
62                 for (int index = 0; index < programJars.size(); index++)
63                 {
64                     // Update the input and output modification times.
65                     ClassPathEntry classPathEntry = programJars.get(index);
66 
67                     checker.updateModificationTime(classPathEntry.getFile(),
68                                                    classPathEntry.isOutput());
69                 }
70             }
71 
72             // Check the dates of the library jars, if any.
73             if (libraryJars != null)
74             {
75                 for (int index = 0; index < libraryJars.size(); index++)
76                 {
77                     // Update the input modification time.
78                     ClassPathEntry classPathEntry = libraryJars.get(index);
79 
80                     checker.updateModificationTime(classPathEntry.getFile(),
81                                                    false);
82                 }
83             }
84 
85             // Check the dates of the auxiliary input files.
86             checker.updateInputModificationTime(configuration.applyMapping);
87             checker.updateInputModificationTime(configuration.obfuscationDictionary);
88             checker.updateInputModificationTime(configuration.classObfuscationDictionary);
89             checker.updateInputModificationTime(configuration.packageObfuscationDictionary);
90 
91             // Check the dates of the auxiliary output files.
92             checker.updateOutputModificationTime(configuration.printSeeds);
93             checker.updateOutputModificationTime(configuration.printUsage);
94             checker.updateOutputModificationTime(configuration.printMapping);
95             checker.updateOutputModificationTime(configuration.printConfiguration);
96             checker.updateOutputModificationTime(configuration.dump);
97         }
98         catch (IllegalStateException e)
99         {
100             // The output is outdated.
101             return false;
102         }
103 
104         System.out.println("The output seems up to date");
105 
106         return true;
107     }
108 
109 
110     /**
111      * This class maintains the modification times of input and output.
112      * The methods throw an IllegalStateException if the output appears
113      * outdated.
114      */
115     private static class ModificationTimeChecker {
116 
117         private long inputModificationTime  = Long.MIN_VALUE;
118         private long outputModificationTime = Long.MAX_VALUE;
119 
120 
121         /**
122          * Updates the input modification time based on the given file or
123          * directory (recursively).
124          */
updateInputModificationTime(File file)125         public void updateInputModificationTime(File file)
126         {
127             if (file != null)
128             {
129                 updateModificationTime(file, false);
130             }
131         }
132 
133 
134         /**
135          * Updates the input modification time based on the given file or
136          * directory (recursively).
137          */
updateOutputModificationTime(File file)138         public void updateOutputModificationTime(File file)
139         {
140             if (file != null && file.getName().length() > 0)
141             {
142                 updateModificationTime(file, true);
143             }
144         }
145 
146 
147         /**
148          * Updates the specified modification time based on the given file or
149          * directory (recursively).
150          */
updateModificationTime(File file, boolean isOutput)151         public void updateModificationTime(File file, boolean isOutput)
152         {
153             // Is it a directory?
154             if (file.isDirectory())
155             {
156                 // Ignore the directory's modification time; just recurse on
157                 // its files.
158                 File[] files = file.listFiles();
159 
160                 // Still, an empty output directory is probably a sign that it
161                 // is not up to date.
162                 if (files.length == 0 && isOutput)
163                 {
164                     updateOutputModificationTime(Long.MIN_VALUE);
165                 }
166 
167                 for (int index = 0; index < files.length; index++)
168                 {
169                     updateModificationTime(files[index], isOutput);
170                 }
171             }
172             else
173             {
174                 // Update with the file's modification time.
175                 updateModificationTime(file.lastModified(), isOutput);
176             }
177         }
178 
179 
180         /**
181          * Updates the specified modification time.
182          */
updateModificationTime(long time, boolean isOutput)183         public void updateModificationTime(long time, boolean isOutput)
184         {
185             if (isOutput)
186             {
187                 updateOutputModificationTime(time);
188             }
189             else
190             {
191                 updateInputModificationTime(time);
192             }
193         }
194 
195 
196         /**
197          * Updates the input modification time.
198          */
updateInputModificationTime(long time)199         public void updateInputModificationTime(long time)
200         {
201             if (inputModificationTime < time)
202             {
203                 inputModificationTime = time;
204 
205                 checkModificationTimes();
206             }
207         }
208 
209 
210         /**
211          * Updates the output modification time.
212          */
updateOutputModificationTime(long time)213         public void updateOutputModificationTime(long time)
214         {
215             if (outputModificationTime > time)
216             {
217                 outputModificationTime = time;
218 
219                 checkModificationTimes();
220             }
221         }
222 
223 
checkModificationTimes()224         private void checkModificationTimes()
225         {
226             if (inputModificationTime > outputModificationTime)
227             {
228                 throw new IllegalStateException("The output is outdated");
229             }
230         }
231     }
232 }
233