com.redhat.ceylon.ant.LazyHelper Maven / Gradle / Ivy
/*
* Copyright Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the authors tag. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License version 2.
*
* This particular file is subject to the "Classpath" exception as provided in the
* LICENSE file that accompanied this code.
*
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License,
* along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package com.redhat.ceylon.ant;
import java.io.File;
import java.io.FileFilter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import org.apache.tools.ant.Project;
import com.redhat.ceylon.common.Constants;
import com.redhat.ceylon.common.ModuleDescriptorReader;
import com.redhat.ceylon.common.ModuleDescriptorReader.NoSuchModuleException;
import com.redhat.ceylon.launcher.ClassLoaderSetupException;
/**
* Encapsulates file modification time logic for figuring out whether a tool
* execution is actually required: Are any sources newer than the output.
* @author tom
*/
abstract class LazyHelper {
private final Lazy task;
public LazyHelper(Lazy task) {
this.task = task;
}
long newestFile(List dirs, File moduleDir) {
long newest = Long.MIN_VALUE;
for (File dir : dirs) {
File fullModuleDir = new File(dir, moduleDir.getPath());
newest = newestFile(newest, fullModuleDir);
task.log("Newest file in " + fullModuleDir + " " + new Date(newest), Project.MSG_DEBUG);
}
return newest;
}
long newestFile(long mtime, File file) {
if (file.isDirectory()) {
for (File child : file.listFiles()) {
mtime = Math.max(mtime, newestFile(mtime, child));
}
} else {
long lastModified = file.lastModified();
task.log(file + " last modified " + new Date(lastModified), Project.MSG_DEBUG);
mtime = Math.max(mtime, lastModified);
}
return mtime;
}
long oldestOutputArtifact(long mtime, File file) {
if (file.isDirectory()) {
for (File child : file.listFiles()) {
mtime = Math.min(mtime, oldestOutputArtifact(mtime, child));
}
} else if (getArtifactFilter().accept(file)) {
long time = getOldestArtifactTime(file);
task.log(file + " oldest time " + new Date(time), Project.MSG_DEBUG);
mtime = Math.min(mtime, time);
}
return mtime;
}
/**
* Filters out all the modules which appear to not require
* compilation based on comparison of file modification times
* @return true if everything was filtered out
*/
protected boolean filterModules(Collection modules) {
if (task.getNoMtimeCheck() || isOutputRepositoryURL()) {
return false;
}
Iterator iterator = modules.iterator();
while (iterator.hasNext()) {
Module m = iterator.next();
Module module = findModule(m.getName());
if (module == null || module.getVersion() == null) {
task.log("Module " + m.getName() + " could not be found (or unable to determine version and hence timestamp)", Project.MSG_VERBOSE);
continue;
}
long newest = Math.max(newestFile(task.getSrc(), module.toDir()), newestFile(task.getResource(), module.toDir()));
File outModuleDir = getArtifactDir(module);
long oldest = oldestOutputArtifact(Long.MAX_VALUE, outModuleDir);
task.log("Oldest file in " + outModuleDir + " " + new Date(oldest), Project.MSG_DEBUG);
if (newest != Long.MIN_VALUE
&& oldest != Long.MAX_VALUE
&& newest < oldest) {
task.log("No need to compile " + module + ", it's up to date");
iterator.remove();
}
}
return modules.size() == 0;
}
private boolean isOutputRepositoryURL() {
String out = task.getOut();
if(out == null || out.isEmpty())
return false;
try{
new URL(out);
return true;
}catch(MalformedURLException x){
return false;
}
}
/**
* Filters out all the source files which appear to not require
* compilation based on comparison of file modification times
* @return true if everything was filtered out
*/
protected boolean filterFiles(List files) {
if (task.getNoMtimeCheck() || isOutputRepositoryURL()) {
return false;
}
Iterator iter = files.iterator();
while (iter.hasNext()) {
File file = iter.next();
Module module = inferModule(file);
if (module == null) {
task.log("Unable to determine module of " + file, Project.MSG_VERBOSE);
continue;
}
if (module.getVersion() == null) {
task.log("Unable to determine version (and hence timestamp) of " + module.getName(), Project.MSG_VERBOSE);
continue;
}
long oldest = getArtifactFileTime(module, file);
if (oldest == Long.MAX_VALUE) {
File outModuleDir = getArtifactDir(module);
oldest = oldestOutputArtifact(Long.MAX_VALUE, outModuleDir);
task.log("Oldest file for " + module + " " + new Date(oldest), Project.MSG_DEBUG);
} else {
task.log("Artifact file associated with " + file + " for " + module + " " + new Date(oldest), Project.MSG_DEBUG);
}
long newestFile = file.lastModified();
task.log("File " + file + " last modified " + new Date(newestFile), Project.MSG_DEBUG);
if (newestFile != Long.MIN_VALUE
&& oldest != Long.MAX_VALUE
&& newestFile < oldest) {
task.log("No need to compile " + file + ", it's up to date");
iter.remove();
}
}
return files.size() == 0;
}
protected abstract File getArtifactDir(Module module);
protected abstract FileFilter getArtifactFilter();
protected abstract long getOldestArtifactTime(File file);
protected abstract long getArtifactFileTime(Module module, File file);
private Module findModule(String moduleName) {
for (File src : task.getSrc()) {
try{
ModuleDescriptorReader mdr = new ModuleDescriptorReader(task.getClassLoader(), moduleName, src);
if (mdr.getModuleVersion() != null) {
return new Module(mdr.getModuleName(), mdr.getModuleVersion());
}
}catch(ModuleDescriptorReader.NoSuchModuleException x){
continue;
}catch(ClassLoaderSetupException x){
// not like we can try again
return null;
}
}
return null;
}
private Module inferModule(File file) {
if (file.exists()) {
for (File src : task.getSrc()) {
if (Util.isChildOfOrEquals(src, file)) {
while (!file.equals(src)) {
File moduleDescriptor = file.isDirectory() ? new File(file, Constants.MODULE_DESCRIPTOR) : file;
if (moduleDescriptor.exists()
&& moduleDescriptor.getName().equals(Constants.MODULE_DESCRIPTOR)) {
String moduleName = moduleDescriptor.getParentFile().getAbsolutePath().substring(src.getAbsolutePath().length()+1).replace(File.separator, ".");
try {
ModuleDescriptorReader mdr = new ModuleDescriptorReader(task.getClassLoader(), moduleName, src);
return new Module(mdr.getModuleName(), mdr.getModuleVersion());
} catch (NoSuchModuleException e) {
continue;
} catch (ClassLoaderSetupException e) {
// not like we can try again
return null;
}
}
file = file.getParentFile();
}
}
}
}
return null;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy