1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/* 2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ProGuard -- shrinking, optimization, obfuscation, and preverification 3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * of Java bytecode. 4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 52270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Copyright (c) 2002-2014 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 { 50b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang try 51b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 52b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang ModificationTimeChecker checker = new ModificationTimeChecker(); 53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 54b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang checker.updateInputModificationTime(configuration.lastModified); 55cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang 56b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang ClassPath programJars = configuration.programJars; 57b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang ClassPath libraryJars = configuration.libraryJars; 58b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 59b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Check the dates of the program jars, if any. 60b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (programJars != null) 61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 62b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang for (int index = 0; index < programJars.size(); index++) 63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 64b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the input and output modification times. 65b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang ClassPathEntry classPathEntry = programJars.get(index); 66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 67b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang checker.updateModificationTime(classPathEntry.getFile(), 68b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang classPathEntry.isOutput()); 69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 70cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang } 71cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang 72b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Check the dates of the library jars, if any. 73b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (libraryJars != null) 74cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang { 75b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang for (int index = 0; index < libraryJars.size(); index++) 76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 77b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the input modification time. 78b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang ClassPathEntry classPathEntry = libraryJars.get(index); 79cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang 80b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang checker.updateModificationTime(classPathEntry.getFile(), 81b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang false); 82cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang } 83cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang } 84cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang 85b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Check the dates of the auxiliary input files. 86b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang checker.updateInputModificationTime(configuration.applyMapping); 87b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang checker.updateInputModificationTime(configuration.obfuscationDictionary); 88b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang checker.updateInputModificationTime(configuration.classObfuscationDictionary); 89b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang checker.updateInputModificationTime(configuration.packageObfuscationDictionary); 90b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 91b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Check the dates of the auxiliary output files. 92b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang checker.updateOutputModificationTime(configuration.printSeeds); 93b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang checker.updateOutputModificationTime(configuration.printUsage); 94b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang checker.updateOutputModificationTime(configuration.printMapping); 95b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang checker.updateOutputModificationTime(configuration.printConfiguration); 96b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang checker.updateOutputModificationTime(configuration.dump); 97b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 98b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang catch (IllegalStateException e) 99cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang { 100b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // The output is outdated. 101b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang return false; 102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 103cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang 104b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang System.out.println("The output seems up to date"); 105b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 106b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang return true; 1079f606f95f03a75961498803e24bee6799a7c0885Ying Wang } 108cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang 109cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang 1109f606f95f03a75961498803e24bee6799a7c0885Ying Wang /** 111b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * This class maintains the modification times of input and output. 112b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * The methods throw an IllegalStateException if the output appears 113b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * outdated. 1149f606f95f03a75961498803e24bee6799a7c0885Ying Wang */ 115b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang private static class ModificationTimeChecker { 116b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 117b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang private long inputModificationTime = Long.MIN_VALUE; 118b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang private long outputModificationTime = Long.MAX_VALUE; 119b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 120b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 121b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang /** 122b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * Updates the input modification time based on the given file or 123b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * directory (recursively). 124b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang */ 125b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang public void updateInputModificationTime(File file) 1269f606f95f03a75961498803e24bee6799a7c0885Ying Wang { 127b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (file != null) 128b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 129b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang updateModificationTime(file, false); 130b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 131b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 132cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang 133cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang 134b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang /** 135b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * Updates the input modification time based on the given file or 136b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * directory (recursively). 137b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang */ 138b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang public void updateOutputModificationTime(File file) 139b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 140b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (file != null && file.getName().length() > 0) 141cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang { 142b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang updateModificationTime(file, true); 143b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 144b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 145b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 146b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 147b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang /** 148b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * Updates the specified modification time based on the given file or 149b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * directory (recursively). 150b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang */ 151b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang public void updateModificationTime(File file, boolean isOutput) 152b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 153b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Is it a directory? 154b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (file.isDirectory()) 155b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 156b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Ignore the directory's modification time; just recurse on 157b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // its files. 158b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang File[] files = file.listFiles(); 159b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 160b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Still, an empty output directory is probably a sign that it 161b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // is not up to date. 162b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (files.length == 0 && isOutput) 1639f606f95f03a75961498803e24bee6799a7c0885Ying Wang { 164b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang updateOutputModificationTime(Long.MIN_VALUE); 1659f606f95f03a75961498803e24bee6799a7c0885Ying Wang } 166b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 167b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang for (int index = 0; index < files.length; index++) 168b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 169b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang updateModificationTime(files[index], isOutput); 170b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 171b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 172b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang else 173b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 174b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update with the file's modification time. 175b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang updateModificationTime(file.lastModified(), isOutput); 176cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang } 177b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 178b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 179cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang 180b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang /** 181b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * Updates the specified modification time. 182b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang */ 183b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang public void updateModificationTime(long time, boolean isOutput) 184b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 185b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (isOutput) 186b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 187b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang updateOutputModificationTime(time); 188b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 189b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang else 190b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 191b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang updateInputModificationTime(time); 192b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 1939f606f95f03a75961498803e24bee6799a7c0885Ying Wang } 194b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 195b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 196b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang /** 197b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * Updates the input modification time. 198b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang */ 199b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang public void updateInputModificationTime(long time) 200cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang { 201b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (inputModificationTime < time) 202b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 203b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang inputModificationTime = time; 204b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 205b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang checkModificationTimes(); 206b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 207b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 208b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 209b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 210b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang /** 211b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * Updates the output modification time. 212b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang */ 213b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang public void updateOutputModificationTime(long time) 214b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 215b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (outputModificationTime > time) 216b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 217b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang outputModificationTime = time; 218b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 219b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang checkModificationTimes(); 220b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 221b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 222b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 223b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 224b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang private void checkModificationTimes() 225b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 226b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (inputModificationTime > outputModificationTime) 227b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 228b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang throw new IllegalStateException("The output is outdated"); 229b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 230b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 231b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 232b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato} 233