From 6adc5398b737025eb6fc6a617c1efd3d1e1a0e60 Mon Sep 17 00:00:00 2001 From: kitfox Date: Thu, 12 Apr 2007 20:38:28 +0000 Subject: Pseudocode for main rendering logic. Roughing in SVG structure. git-svn-id: https://svn.java.net/svn/svgsalamander~svn/trunk/svg-core@12 7dc7fa77-23fb-e6ad-8e2e-c86bd48ed22b --- .../com/kitfox/util/ServicesListerAntTask.java | 316 +++++++++++++++++++++ 1 file changed, 316 insertions(+) create mode 100755 src/main/java/com/kitfox/util/ServicesListerAntTask.java diff --git a/src/main/java/com/kitfox/util/ServicesListerAntTask.java b/src/main/java/com/kitfox/util/ServicesListerAntTask.java new file mode 100755 index 0000000..225ac91 --- /dev/null +++ b/src/main/java/com/kitfox/util/ServicesListerAntTask.java @@ -0,0 +1,316 @@ +/* + * ServicesListerAntTask.java + * + * Created on September 17, 2006, 4:08 AM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.kitfox.util; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import org.apache.tools.ant.taskdefs.DefBase; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.Path; +import org.apache.tools.ant.types.Resource; +import org.apache.tools.ant.types.resources.FileResource; + +/** + * This ant task examines a directory hierarchy containing .class files and + * constructs lists of all classes that extend a given base class. This + * is meant to facilitate the generation of META-INF/services lists + * for jar files. + * + * + * <servicesLister> + * <examinepath> + * <pathelement location="${path-to-find-classfiles-to-be-analyzed}"> + * </examinepath> + * <classpath> + * <pathelement location="${classpath-needed-to-construct-Class-objects-of-classes-in-examine-path}"> + * </classpath> + * <service className="name.of.class.to.build.list.For1" toDir="location/to/save/generated.list1"> + * <service className="name.of.class.to.build.list.For2" toDir="location/to/save/generated.list2"> + * </servicesLister> + * + * + * @author kitfox + */ +public class ServicesListerAntTask extends DefBase +{ + /** + * Contains info for a single service to generate a list for. There may be + * zero or more services tags embedded in the servicesLister task. + * + * If the toFile parameter is set to the name of a directory, the output + * file name is computed at new File(toFile, className) + */ + public class Service + { + private String className; + private File toFile; + private File toDir; + private Class targetClass; + + ArrayList targets = new ArrayList(); + + public String getClassName() + { + return className; + } + + public void setClassName(String className) + { + this.className = className; + } + + public File getToFile() + { + return toFile; + } + + public void setToFile(File toFile) + { + this.toFile = toFile; + } + + public File getToDir() + { + return toDir; + } + + public void setToDir(File toDir) + { + if (toDir.exists() && !toDir.isDirectory()) + { + throw new BuildException("toDir argument must be a directory: " + toDir); + } + this.toDir = toDir; + } + + public Class getTargetClass() + { + return targetClass; + } + + public void setTargetClass(Class targetClass) + { + this.targetClass = targetClass; + } + + private void writeTarget(String className) + { + targets.add(className); + } + + private void writeToFile() + { + try + { + if (toFile != null) + { + if (toFile.exists() && toFile.isDirectory()) + { + toFile = new File(toFile, className); + } + } + else + { + if (toDir == null) + { + throw new BuildException("Must specify either a toFile or a toDir parameter"); + } + toFile = new File(toDir, className); + } + + + //Make sure parent directory exists + File parent = toFile.getParentFile(); + if (!parent.exists()) + { + parent.mkdirs(); + } + + FileWriter fout = new FileWriter(toFile); + PrintWriter pw = new PrintWriter(new BufferedWriter(fout)); + + pw.println("#Automatically generated services list"); + pw.println("#Mark McKay - " + new Date()); + + for (String target: targets) + { + pw.println(target); + } + + pw.close(); + } + catch (IOException e) + { + throw new BuildException(e); + } + } + } + + Path examinePath; +// ResourceCollection targetRes; + ArrayList services = new ArrayList(); + + /** + * The examine path should be a subset of the classpath and include all the + * classes that should be examined for possible inclusion in the services list. + */ + public Path createExaminePath() throws BuildException + { + if (examinePath == null) + { + examinePath = new Path(getProject()); + return examinePath; + } + throw new BuildException("Only one examine path can be set"); + } + + /* + public void addFileSet(FileSet fileSet) + { + if (this.targetRes != null) + { + throw new BuildException("Resources to be examined set multiple times"); + } + this.targetRes = fileSet; + } + */ + + public Service createService() + { + Service service = new Service(); + services.add(service); + return service; + } + + /** + * Creates a new instance of ServicesListerAntTask + */ + public ServicesListerAntTask() + { + } + + static final FilenameFilter FFILTER_CLASS = new FilenameFilter() + { + public boolean accept(File dir, String name) + { + return name.endsWith(".class"); + } + }; + + public void scanPath(ClassLoader loader, File dir, File pathRoot) + { + String pathAbs = pathRoot.getAbsolutePath(); +//System.err.println("***Abs path: " + pathAbs); +// File[] fileList = dir.listFiles(FFILTER_CLASS); + for (File file: dir.listFiles()) + { + if (file.getName().endsWith(".class")) + { + String fileAbs = file.getAbsolutePath(); +//System.err.println("***Abs file: " + fileAbs); + String relName = fileAbs.substring(pathAbs.length() + 1, fileAbs.length() - ".class".length()); + relName = relName.replaceAll("[/\\\\]", "."); +//System.err.println("***Rel name: " + relName); + Class cls; + try + { + cls = loader.loadClass(relName); + } + catch (ClassNotFoundException ex) + { + throw new BuildException(ex); + } + + if (cls == null) + { + log("Could not examine class " + file); + continue; + } + else + { + //Ignore classes that cannot be instantiated + int mod = cls.getModifiers(); + if (!Modifier.isPublic(mod) || Modifier.isAbstract(mod) || Modifier.isInterface(mod)) + { + continue; + } + } + + for (Service service: services) + { + if (service.getTargetClass().isAssignableFrom(cls)) + { + service.writeTarget(relName); + } + } + } + else if (file.isDirectory()) + { + scanPath(loader, file, pathRoot); + } + } + } + + public void execute() throws BuildException + { + if (examinePath == null) + { + throw new BuildException("Examine path not set - please specify path to files to check for services"); + } + + ClassLoader loader = createLoader(); + + for (Service service: services) + { + String name = service.getClassName(); + Class cls; + try + { + cls = loader.loadClass(name); + } + catch (ClassNotFoundException ex) + { + throw new BuildException(String.format("Could not find %s in classpath", name), ex); + } + service.setTargetClass(cls); + } + + + for (Iterator it = examinePath.iterator(); it.hasNext();) + { + Resource res = (Resource)it.next(); + if (!(res instanceof FileResource)) continue; + +//System.err.println("*****Resource " + res.getName() + ", " + res.getClass().getName() + ", " + res.toString()); + File root = ((FileResource)res).getFile(); +//System.err.println("*****File " + Name() + " " + res); + + //Find all .class files under the path + scanPath(loader, root, root); + } + + + //Write all to disk + for (Service service: services) + { + service.writeToFile(); + } + + } + +} -- cgit v1.2.3-55-g7522