001 /* ======================================================================== 002 * JCommon : a free general purpose class library for the Java(tm) platform 003 * ======================================================================== 004 * 005 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. 006 * 007 * Project Info: http://www.jfree.org/jcommon/index.html 008 * 009 * This library is free software; you can redistribute it and/or modify it 010 * under the terms of the GNU Lesser General Public License as published by 011 * the Free Software Foundation; either version 2.1 of the License, or 012 * (at your option) any later version. 013 * 014 * This library is distributed in the hope that it will be useful, but 015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 017 * License for more details. 018 * 019 * You should have received a copy of the GNU Lesser General Public 020 * License along with this library; if not, write to the Free Software 021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 022 * USA. 023 * 024 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 025 * in the United States and other countries.] 026 * 027 * ------------------------ 028 * JavaSourceCollector.java 029 * ------------------------ 030 * (C)opyright 2003, 2004, by Thomas Morgner and Contributors. 031 * 032 * Original Author: Thomas Morgner; 033 * Contributor(s): David Gilbert (for Object Refinery Limited); 034 * 035 * $Id: JavaSourceCollector.java,v 1.3 2005/10/18 13:32:20 mungady Exp $ 036 * 037 * Changes 038 * ------------------------- 039 * 21.06.2003 : Initial version 040 * 041 */ 042 043 package org.jfree.xml.generator; 044 045 import java.io.File; 046 import java.io.FileFilter; 047 import java.lang.reflect.Modifier; 048 import java.util.ArrayList; 049 050 import org.jfree.ui.ExtensionFileFilter; 051 import org.jfree.util.Log; 052 import org.jfree.util.ObjectUtilities; 053 054 /** 055 * The class collects all class-files and loads the class objects named 056 * by these files. 057 */ 058 public class JavaSourceCollector implements SourceCollector { 059 060 /** 061 * A file filter. 062 */ 063 private static class CollectorFileFilter extends ExtensionFileFilter implements FileFilter { 064 /** 065 * Creates a new instance. 066 * 067 * @param description the file description. 068 * @param extension the file extension. 069 */ 070 public CollectorFileFilter(final String description, final String extension) { 071 super(description, extension); 072 } 073 } 074 075 /** A file filter. */ 076 private CollectorFileFilter eff; 077 078 /** The file list. */ 079 private ArrayList fileList; 080 081 /** A list of ignored packages. */ 082 private ArrayList ignoredPackages; 083 084 /** A list of ignored base classes. */ 085 private ArrayList ignoredBaseClasses; 086 087 /** The start directory. */ 088 private File startDirectory; 089 090 /** The initial package name. */ 091 private String initialPackageName; 092 093 /** 094 * Creates a new source collector. 095 * 096 * @param startDirectory the start directory. 097 */ 098 public JavaSourceCollector(final File startDirectory) { 099 this(startDirectory, ""); 100 } 101 102 /** 103 * Creates a new source collector. 104 * 105 * @param startDirectory the base directory. 106 * @param packageName the base package name. 107 */ 108 public JavaSourceCollector(final File startDirectory, final String packageName) { 109 this.eff = new CollectorFileFilter("<ignore>", ".java"); 110 this.fileList = new ArrayList(); 111 this.startDirectory = startDirectory; 112 this.initialPackageName = packageName; 113 this.ignoredPackages = new ArrayList(); 114 this.ignoredBaseClasses = new ArrayList(); 115 } 116 117 /** 118 * Adds a package that should be ignored. 119 * 120 * @param pkg the package name. 121 */ 122 public void addIgnoredPackage(final String pkg) { 123 Log.debug (new Log.SimpleMessage("Added IgnPackage: " , pkg)); 124 this.ignoredPackages.add(pkg); 125 } 126 127 /** 128 * Adds a base class that should be ignored. 129 * 130 * @param baseClass the base class name. 131 */ 132 public void addIgnoredBaseClass(final String baseClass) { 133 final Class loadedClass = loadClass(baseClass); 134 if (loadedClass != null) { 135 Log.debug (new Log.SimpleMessage("Added IgnClass: " , baseClass)); 136 this.ignoredBaseClasses.add(loadedClass); 137 } 138 } 139 140 /** 141 * Adds a class to the list of ignored base classes. 142 * 143 * @param baseClass the class. 144 */ 145 public void addIgnoredBaseClass(final Class baseClass) { 146 this.ignoredBaseClasses.add(baseClass); 147 } 148 149 /** 150 * Returns <code>true</code> if the named class is being ignored (because of the package that 151 * it belongs to), and <code>false</code> otherwise. 152 * 153 * @param classname the name of the class to test. 154 * 155 * @return A boolean. 156 */ 157 protected boolean isIgnoredPackage(final String classname) { 158 for (int i = 0; i < this.ignoredPackages.size(); i++) { 159 final String ignoredPackage = (String) this.ignoredPackages.get(i); 160 if (classname.startsWith(ignoredPackage)) { 161 return true; 162 } 163 } 164 return false; 165 } 166 167 /** 168 * Returns <code>true</code> if the named class is being ignored (because it is a descendant 169 * of an ignored base class), and <code>false</code> otherwise. 170 * 171 * @param c the class name. 172 * 173 * @return A boolean. 174 */ 175 protected boolean isIgnoredBaseClass(final Class c) { 176 for (int i = 0; i < this.ignoredBaseClasses.size(); i++) { 177 final Class ignoredClass = (Class) this.ignoredBaseClasses.get(i); 178 if (ignoredClass.isAssignableFrom(c)) { 179 return true; 180 } 181 } 182 return false; 183 } 184 185 /** 186 * Collects the files/classes. 187 */ 188 public void collectFiles() { 189 collectFiles(this.startDirectory, this.initialPackageName); 190 } 191 192 /** 193 * Collects the files/classes. 194 * 195 * @param directory the starting directory. 196 * @param packageName the initial package name. 197 */ 198 protected void collectFiles(final File directory, final String packageName) { 199 final File[] files = directory.listFiles(this.eff); 200 for (int i = 0; i < files.length; i++) { 201 if (files[i].isDirectory()) { 202 collectFiles(files[i], buildJavaName(packageName, files[i].getName())); 203 } 204 else { 205 final String fname = files[i].getName(); 206 final String className = fname.substring(0, fname.length() - 5); 207 final String fullName = buildJavaName(packageName, className); 208 if (isIgnoredPackage(fullName)) { 209 Log.debug (new Log.SimpleMessage("Do not process: Ignored: ", className)); 210 continue; 211 } 212 final Class jclass = loadClass(fullName); 213 if (jclass == null || isIgnoredBaseClass(jclass)) { 214 continue; 215 } 216 if (jclass.isInterface() || Modifier.isAbstract(jclass.getModifiers())) { 217 Log.debug (new Log.SimpleMessage("Do not process: Abstract: ", className)); 218 continue; 219 } 220 if (!Modifier.isPublic(jclass.getModifiers())) { 221 Log.debug (new Log.SimpleMessage("Do not process: Not public: ", className)); 222 continue; 223 } 224 this.fileList.add(jclass); 225 } 226 } 227 } 228 229 /** 230 * Loads a class by its fully qualified name. 231 * 232 * @param name the class name. 233 * 234 * @return The class (or <code>null</code> if there was a problem loading the class). 235 */ 236 protected Class loadClass(final String name) { 237 try { 238 return ObjectUtilities.getClassLoader(JavaSourceCollector.class).loadClass(name); 239 } 240 catch (Exception e) { 241 Log.warn (new Log.SimpleMessage("Do not process: Failed to load class:", name)); 242 return null; 243 } 244 } 245 246 /** 247 * Creates a fully qualified Java class or package name. 248 * 249 * @param packageName the base package name. 250 * @param newPackage the class/package name. 251 * 252 * @return The fully qualified package/class name. 253 */ 254 protected String buildJavaName(final String packageName, final String newPackage) { 255 if (packageName.length() == 0) { 256 return newPackage; 257 } 258 else { 259 return packageName + "." + newPackage; 260 } 261 } 262 263 /** 264 * Returns the list of classes as an array. 265 * 266 * @return The list of classes. 267 */ 268 public Class[] getClasses() { 269 return (Class[]) this.fileList.toArray(new Class[0]); 270 } 271 272 }