Source for org.jfree.xml.generator.JavaSourceCollector

   1: /* ========================================================================
   2:  * JCommon : a free general purpose class library for the Java(tm) platform
   3:  * ========================================================================
   4:  *
   5:  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
   6:  * 
   7:  * Project Info:  http://www.jfree.org/jcommon/index.html
   8:  *
   9:  * This library is free software; you can redistribute it and/or modify it 
  10:  * under the terms of the GNU Lesser General Public License as published by 
  11:  * the Free Software Foundation; either version 2.1 of the License, or 
  12:  * (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but 
  15:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  16:  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
  17:  * License for more details.
  18:  *
  19:  * You should have received a copy of the GNU Lesser General Public
  20:  * License along with this library; if not, write to the Free Software
  21:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
  22:  * USA.  
  23:  *
  24:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
  25:  * in the United States and other countries.]
  26:  * 
  27:  * ------------------------
  28:  * JavaSourceCollector.java
  29:  * ------------------------
  30:  * (C)opyright 2003, 2004, by Thomas Morgner and Contributors.
  31:  *
  32:  * Original Author:  Thomas Morgner;
  33:  * Contributor(s):   David Gilbert (for Object Refinery Limited);
  34:  *
  35:  * $Id: JavaSourceCollector.java,v 1.3 2005/10/18 13:32:20 mungady Exp $
  36:  *
  37:  * Changes
  38:  * -------------------------
  39:  * 21.06.2003 : Initial version
  40:  *
  41:  */
  42: 
  43: package org.jfree.xml.generator;
  44: 
  45: import java.io.File;
  46: import java.io.FileFilter;
  47: import java.lang.reflect.Modifier;
  48: import java.util.ArrayList;
  49: 
  50: import org.jfree.ui.ExtensionFileFilter;
  51: import org.jfree.util.Log;
  52: import org.jfree.util.ObjectUtilities;
  53: 
  54: /**
  55:  * The class collects all class-files and loads the class objects named
  56:  * by these files.
  57:  */
  58: public class JavaSourceCollector implements SourceCollector {
  59: 
  60:     /**
  61:      * A file filter.
  62:      */
  63:     private static class CollectorFileFilter extends ExtensionFileFilter implements FileFilter {
  64:         /**
  65:          * Creates a new instance.
  66:          * 
  67:          * @param description  the file description.
  68:          * @param extension  the file extension.
  69:          */
  70:         public CollectorFileFilter(final String description, final String extension) {
  71:             super(description, extension);
  72:         }
  73:     }
  74: 
  75:     /** A file filter. */
  76:     private CollectorFileFilter eff;
  77:     
  78:     /** The file list. */
  79:     private ArrayList fileList;
  80:     
  81:     /** A list of ignored packages. */
  82:     private ArrayList ignoredPackages;
  83: 
  84:     /** A list of ignored base classes. */
  85:     private ArrayList ignoredBaseClasses;
  86:     
  87:     /** The start directory. */
  88:     private File startDirectory;
  89:     
  90:     /** The initial package name. */
  91:     private String initialPackageName;
  92: 
  93:     /**
  94:      * Creates a new source collector.
  95:      * 
  96:      * @param startDirectory  the start directory.
  97:      */
  98:     public JavaSourceCollector(final File startDirectory) {
  99:         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: }