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