Browse Source

Subclass of fileset which given a root class will return the closure of all

classes upon which that class depends.

Submitted by:	Holger Engels <hengels@mercatis.de>


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269884 13f79535-47bb-0310-9956-ffa450edef68
master
Conor MacNeill 23 years ago
parent
commit
2ab27c7552
6 changed files with 626 additions and 1 deletions
  1. +10
    -1
      build.xml
  2. +1
    -0
      src/main/org/apache/tools/ant/types/defaults.properties
  3. +102
    -0
      src/main/org/apache/tools/ant/types/optional/depend/ClassfileSet.java
  4. +192
    -0
      src/main/org/apache/tools/ant/types/optional/depend/DependScanner.java
  5. +261
    -0
      src/main/org/apache/tools/ant/util/depend/Dependencies.java
  6. +60
    -0
      src/main/org/apache/tools/ant/util/depend/Filter.java

+ 10
- 1
build.xml View File

@@ -36,7 +36,9 @@
<property name="ant.package" value="org/apache/tools/ant"/>
<property name="optional.package" value="${ant.package}/taskdefs/optional"/>
<property name="regexp.package" value="${ant.package}/util/regexp"/>
<property name="optional.type.package" value="${ant.package}/types/optional"/>
<property name="util.package" value="${ant.package}/util"/>
<property name="regexp.package" value="${util.package}/regexp"/>

<property name="manifest" value="src/etc/manifest"/>

@@ -176,6 +178,9 @@
<available property="xerces.present"
classname="org.apache.xerces.parsers.SAXParser"
classpathref="classpath" />
<available property="bcel.present"
classname="de.fub.bytecode.Constants"
classpathref="classpath" />
<condition property="javamail.complete">
<and>
@@ -284,6 +289,10 @@
<exclude name="${optional.package}/metamata/**" unless="jdk1.2+" />
<exclude name="${optional.package}/ManifestFile.java"
unless="jdk1.2+" />
<exclude name="${optional.type.package}/depend/*.java"
unless="bcel.present" />
<exclude name="${util.package}/depend/*.java"
unless="bcel.present" />
</javac>
<copy todir="${build.classes}">


+ 1
- 0
src/main/org/apache/tools/ant/types/defaults.properties View File

@@ -5,4 +5,5 @@ patternset=org.apache.tools.ant.types.PatternSet
mapper=org.apache.tools.ant.types.Mapper
filterset=org.apache.tools.ant.types.FilterSet
description=org.apache.tools.ant.types.Description
classfileset=org.apache.tools.ant.types.optional.depend.ClassfileSet


+ 102
- 0
src/main/org/apache/tools/ant/types/optional/depend/ClassfileSet.java View File

@@ -0,0 +1,102 @@
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Ant", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.types.optional.depend;

import java.io.File;
import java.util.Stack;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.util.depend.Dependencies;

/**
* A DepSet is a FileSet, that enlists all classes that depend on a
* certain class.
*
* A DependSet extends FileSets and uses another FileSet as input. The
* nested FileSet attribute provides the domain, that is used for searching
* for dependent classes
*
* @author <a href="mailto:hengels@innovidata.com">Holger Engels</a>
*/
public class ClassfileSet extends FileSet {
private File baseClass = null;

/**
* Set the directory for the fileset. Prevents both "dir" and "src"
* from being specified.
*/
public void setBaseClass(File baseClass)
throws BuildException
{
this.baseClass = baseClass;
}

public void setDir(File dir) throws BuildException {
super.setDir(dir);
}


/**
* Return the DirectoryScanner associated with this FileSet.
*/
public DirectoryScanner getDirectoryScanner(Project p) {
DependScanner scanner = new DependScanner();
scanner.setBasedir(getDir(p));
scanner.setBaseClass(baseClass);
scanner.scan();
return scanner;
}
}

+ 192
- 0
src/main/org/apache/tools/ant/types/optional/depend/DependScanner.java View File

@@ -0,0 +1,192 @@
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Ant", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.types.optional.depend;

import java.io.*;
import java.util.*;

import org.apache.tools.ant.util.depend.Dependencies;
import org.apache.tools.ant.util.depend.Filter;
import org.apache.tools.ant.DirectoryScanner;

import de.fub.bytecode.classfile.*;
import de.fub.bytecode.*;

/**
* An interface used to describe the actions required by any type of
* directory scanner.
*/
public class DependScanner extends DirectoryScanner {
File basedir;
File baseClass;
List included = new LinkedList();

/**
* Sets the basedir for scanning. This is the directory that is scanned
* recursively.
*
* @param basedir the (non-null) basedir for scanning
*/
public void setBasedir(String basedir) {
setBasedir(new File(basedir.replace('/',File.separatorChar).replace('\\',File.separatorChar)));
}

/**
* Sets the basedir for scanning. This is the directory that is scanned
* recursively.
*
* @param basedir the basedir for scanning
*/
public void setBasedir(File basedir) {
this.basedir = basedir;
}
/**
* Gets the basedir that is used for scanning.
*
* @return the basedir that is used for scanning
*/
public File getBasedir() { return basedir; }

/**
* Sets the domain, where dependant classes are searched
*
* @param domain the domain
*/
public void setBaseClass(File baseClass) {
this.baseClass = baseClass;
}

/**
* Get the names of the class files, baseClass depends on
*
* @return the names of the files
*/
public String[] getIncludedFiles() {
int count = included.size();
String[] files = new String[count];
for (int i = 0; i < count; i++) {
files[i] = included.get(i) + ".class";
//System.err.println(" " + files[i]);
}
return files;
}

/**
* Scans the base directory for files that baseClass depends on
*
* @exception IllegalStateException when basedir was set incorrecly
*/
public void scan() {
Dependencies visitor = new Dependencies();
Set set = new TreeSet();
Set newSet = new HashSet();
final String base;
String start;
try {
base = basedir.getCanonicalPath() + File.separator;
start = baseClass.getCanonicalPath();
}
catch (Exception e) {
throw new IllegalArgumentException(e.getMessage());
}

start = start.substring(base.length(), start.length() - ".class".length()).replace(File.separatorChar, '/');
System.err.println("start: " + start);

newSet.add(start);
set.add(start);

do {
Iterator i = newSet.iterator();
while (i.hasNext()) {
String fileName = base + ((String)i.next()).replace('/', File.separatorChar) + ".class";

try {
JavaClass javaClass = new ClassParser(fileName).parse();
javaClass.accept(visitor);
}
catch (IOException e) {
System.err.println("exception: " + e.getMessage());
}
}
newSet.clear();
newSet.addAll(visitor.getDependencies());
visitor.clearDependencies();

Dependencies.applyFilter(newSet, new Filter() {
public boolean accept(Object object) {
String fileName = base + ((String)object).replace('/', File.separatorChar) + ".class";
return new File(fileName).exists();
}
});
newSet.removeAll(set);
set.addAll(newSet);
}
while (newSet.size() > 0);

included.clear();
included.addAll(set);
}

public void addDefaultExcludes() {}
public String[] getExcludedDirectories() { return null; };
public String[] getExcludedFiles() { return null; }
public String[] getIncludedDirectories() { return new String[0]; }
public String[] getNotIncludedDirectories() { return null; }
public String[] getNotIncludedFiles() { return null; }

public void setExcludes(String[] excludes) {}
public void setIncludes(String[] includes) {}
public void setCaseSensitive(boolean isCaseSensitive) {}
}

+ 261
- 0
src/main/org/apache/tools/ant/util/depend/Dependencies.java View File

@@ -0,0 +1,261 @@
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Ant", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.util.depend;

import java.io.*;
import java.util.*;
import de.fub.bytecode.classfile.*;
import de.fub.bytecode.*;


public class Dependencies implements Visitor {
private boolean verbose = false;

private JavaClass javaClass;
private ConstantPool constantPool;
private Set dependencies = new HashSet();

public void clearDependencies() {
dependencies.clear();
}
public Set getDependencies() {
return dependencies;
}

public void visitCode(Code obj) {}
public void visitCodeException(CodeException obj) {}
public void visitConstantClass(ConstantClass obj) {
if (verbose) {
System.out.println("visit ConstantClass");
System.out.println(obj.getConstantValue(constantPool));
}
dependencies.add("" + obj.getConstantValue(constantPool));
}
public void visitConstantDouble(ConstantDouble obj) {}
public void visitConstantFieldref(ConstantFieldref obj) {}
public void visitConstantFloat(ConstantFloat obj) {}
public void visitConstantInteger(ConstantInteger obj) {}
public void visitConstantInterfaceMethodref(ConstantInterfaceMethodref obj) {}
public void visitConstantLong(ConstantLong obj) {}
public void visitConstantMethodref(ConstantMethodref obj) {}
public void visitConstantNameAndType(ConstantNameAndType obj) {}
public void visitConstantPool(ConstantPool obj) {
if (verbose)
System.out.println("visit ConstantPool");
this.constantPool = obj;

// visit constants
for(int idx = 0; idx < constantPool.getLength(); idx++) {
Constant c = constantPool.getConstant(idx);
if (c != null) {
c.accept(this);
}
}
}
public void visitConstantString(ConstantString obj) {}
public void visitConstantUtf8(ConstantUtf8 obj) {}
public void visitConstantValue(ConstantValue obj) {}
public void visitDeprecated(Deprecated obj) {}
public void visitExceptionTable(ExceptionTable obj) {}
public void visitField(Field obj) {
if (verbose) {
System.out.println("visit Field");
System.out.println(obj.getSignature());
}
addClasses(obj.getSignature());
}

public void visitInnerClass(InnerClass obj) {}
public void visitInnerClasses(InnerClasses obj) {}
public void visitJavaClass(JavaClass obj) {
if (verbose) {
System.out.println("visit JavaClass");
}
this.javaClass = obj;
dependencies.add(javaClass.getClassName().replace('.', '/'));

// visit constant pool
javaClass.getConstantPool().accept(this);

// visit fields
Field[] fields = obj.getFields();
for(int i=0; i < fields.length; i++) {
fields[i].accept(this);
}

// visit methods
Method[] methods = obj.getMethods();
for(int i=0; i < methods.length; i++) {
methods[i].accept(this);
}
}
public void visitLineNumber(LineNumber obj) {}
public void visitLineNumberTable(LineNumberTable obj) {}
public void visitLocalVariable(LocalVariable obj) {}
public void visitLocalVariableTable(LocalVariableTable obj) {}
public void visitMethod(Method obj) {
if (verbose) {
System.out.println("visit Method");
System.out.println(obj.getSignature());
}
String signature = obj.getSignature();
int pos = signature.indexOf(")");
addClasses(signature.substring(1, pos));
addClasses(signature.substring(pos + 1));
}
public void visitSourceFile(SourceFile obj) {}
public void visitSynthetic(Synthetic obj) {}
public void visitUnknown(Unknown obj) {}
public void visitStackMap(StackMap obj) {}
public void visitStackMapEntry(StackMapEntry obj) {}

void addClasses(String string) {
StringTokenizer tokens = new StringTokenizer(string, ";");
while (tokens.hasMoreTokens()) {
addClass(tokens.nextToken());
}
}

void addClass(String string) {
int pos = string.indexOf('L');
if (pos != -1) {
dependencies.add(string.substring(pos+1));
}
}

public static void main(String[] args) {
try {
Dependencies visitor = new Dependencies();

Set set = new TreeSet();
Set newSet = new HashSet();

int o=0;
String arg = null;
if ("-base".equals(args[0])) {
arg = args[1];
if (!arg.endsWith(File.separator)) {
arg = arg + File.separator;
}
o=2;
}
final String base = arg;

for (int i=o; i < args.length; i++) {
String fileName = args[i].substring(0, args[i].length() - ".class".length());
if (base != null && fileName.startsWith(base))
fileName = fileName.substring(base.length());
newSet.add(fileName);
}
set.addAll(newSet);

do {
Iterator i = newSet.iterator();
while (i.hasNext()) {
String fileName = i.next() + ".class";

if (base != null) {
fileName = base + fileName;
}

JavaClass javaClass = new ClassParser(fileName).parse();
javaClass.accept(visitor);
}
newSet.clear();
newSet.addAll(visitor.getDependencies());
visitor.clearDependencies();

applyFilter(newSet, new Filter() {
public boolean accept(Object object) {
String fileName = object + ".class";
if (base != null)
fileName = base + fileName;
return new File(fileName).exists();
}
});
newSet.removeAll(set);
set.addAll(newSet);
}
while (newSet.size() > 0);

Iterator i = set.iterator();
while (i.hasNext()) {
System.out.println(i.next());
}
}
catch (Exception e) {
System.err.println(e.getMessage());
e.printStackTrace(System.err);
}
}

public static void applyFilter(Collection collection, Filter filter) {
Iterator i = collection.iterator();
while (i.hasNext()) {
Object next = i.next();
if (!filter.accept(next)) {
i.remove();
}
}
}
}

+ 60
- 0
src/main/org/apache/tools/ant/util/depend/Filter.java View File

@@ -0,0 +1,60 @@
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Ant", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.util.depend;

import java.util.*;

public interface Filter {
boolean accept(Object object);
}

Loading…
Cancel
Save