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
064: ExtensionFileFilter implements FileFilter {
065: /**
066: * Creates a new instance.
067: *
068: * @param description the file description.
069: * @param extension the file extension.
070: */
071: public CollectorFileFilter(final String description,
072: final String extension) {
073: super (description, extension);
074: }
075: }
076:
077: /** A file filter. */
078: private CollectorFileFilter eff;
079:
080: /** The file list. */
081: private ArrayList fileList;
082:
083: /** A list of ignored packages. */
084: private ArrayList ignoredPackages;
085:
086: /** A list of ignored base classes. */
087: private ArrayList ignoredBaseClasses;
088:
089: /** The start directory. */
090: private File startDirectory;
091:
092: /** The initial package name. */
093: private String initialPackageName;
094:
095: /**
096: * Creates a new source collector.
097: *
098: * @param startDirectory the start directory.
099: */
100: public JavaSourceCollector(final File startDirectory) {
101: this (startDirectory, "");
102: }
103:
104: /**
105: * Creates a new source collector.
106: *
107: * @param startDirectory the base directory.
108: * @param packageName the base package name.
109: */
110: public JavaSourceCollector(final File startDirectory,
111: final String packageName) {
112: this .eff = new CollectorFileFilter("<ignore>", ".java");
113: this .fileList = new ArrayList();
114: this .startDirectory = startDirectory;
115: this .initialPackageName = packageName;
116: this .ignoredPackages = new ArrayList();
117: this .ignoredBaseClasses = new ArrayList();
118: }
119:
120: /**
121: * Adds a package that should be ignored.
122: *
123: * @param pkg the package name.
124: */
125: public void addIgnoredPackage(final String pkg) {
126: Log.debug(new Log.SimpleMessage("Added IgnPackage: ", pkg));
127: this .ignoredPackages.add(pkg);
128: }
129:
130: /**
131: * Adds a base class that should be ignored.
132: *
133: * @param baseClass the base class name.
134: */
135: public void addIgnoredBaseClass(final String baseClass) {
136: final Class loadedClass = loadClass(baseClass);
137: if (loadedClass != null) {
138: Log.debug(new Log.SimpleMessage("Added IgnClass: ",
139: baseClass));
140: this .ignoredBaseClasses.add(loadedClass);
141: }
142: }
143:
144: /**
145: * Adds a class to the list of ignored base classes.
146: *
147: * @param baseClass the class.
148: */
149: public void addIgnoredBaseClass(final Class baseClass) {
150: this .ignoredBaseClasses.add(baseClass);
151: }
152:
153: /**
154: * Returns <code>true</code> if the named class is being ignored (because of the package that
155: * it belongs to), and <code>false</code> otherwise.
156: *
157: * @param classname the name of the class to test.
158: *
159: * @return A boolean.
160: */
161: protected boolean isIgnoredPackage(final String classname) {
162: for (int i = 0; i < this .ignoredPackages.size(); i++) {
163: final String ignoredPackage = (String) this .ignoredPackages
164: .get(i);
165: if (classname.startsWith(ignoredPackage)) {
166: return true;
167: }
168: }
169: return false;
170: }
171:
172: /**
173: * Returns <code>true</code> if the named class is being ignored (because it is a descendant
174: * of an ignored base class), and <code>false</code> otherwise.
175: *
176: * @param c the class name.
177: *
178: * @return A boolean.
179: */
180: protected boolean isIgnoredBaseClass(final Class c) {
181: for (int i = 0; i < this .ignoredBaseClasses.size(); i++) {
182: final Class ignoredClass = (Class) this .ignoredBaseClasses
183: .get(i);
184: if (ignoredClass.isAssignableFrom(c)) {
185: return true;
186: }
187: }
188: return false;
189: }
190:
191: /**
192: * Collects the files/classes.
193: */
194: public void collectFiles() {
195: collectFiles(this .startDirectory, this .initialPackageName);
196: }
197:
198: /**
199: * Collects the files/classes.
200: *
201: * @param directory the starting directory.
202: * @param packageName the initial package name.
203: */
204: protected void collectFiles(final File directory,
205: final String packageName) {
206: final File[] files = directory.listFiles(this .eff);
207: for (int i = 0; i < files.length; i++) {
208: if (files[i].isDirectory()) {
209: collectFiles(files[i], buildJavaName(packageName,
210: files[i].getName()));
211: } else {
212: final String fname = files[i].getName();
213: final String className = fname.substring(0, fname
214: .length() - 5);
215: final String fullName = buildJavaName(packageName,
216: className);
217: if (isIgnoredPackage(fullName)) {
218: Log.debug(new Log.SimpleMessage(
219: "Do not process: Ignored: ", className));
220: continue;
221: }
222: final Class jclass = loadClass(fullName);
223: if (jclass == null || isIgnoredBaseClass(jclass)) {
224: continue;
225: }
226: if (jclass.isInterface()
227: || Modifier.isAbstract(jclass.getModifiers())) {
228: Log.debug(new Log.SimpleMessage(
229: "Do not process: Abstract: ", className));
230: continue;
231: }
232: if (!Modifier.isPublic(jclass.getModifiers())) {
233: Log.debug(new Log.SimpleMessage(
234: "Do not process: Not public: ", className));
235: continue;
236: }
237: this .fileList.add(jclass);
238: }
239: }
240: }
241:
242: /**
243: * Loads a class by its fully qualified name.
244: *
245: * @param name the class name.
246: *
247: * @return The class (or <code>null</code> if there was a problem loading the class).
248: */
249: protected Class loadClass(final String name) {
250: try {
251: return ObjectUtilities.getClassLoader(
252: JavaSourceCollector.class).loadClass(name);
253: } catch (Exception e) {
254: Log.warn(new Log.SimpleMessage(
255: "Do not process: Failed to load class:", name));
256: return null;
257: }
258: }
259:
260: /**
261: * Creates a fully qualified Java class or package name.
262: *
263: * @param packageName the base package name.
264: * @param newPackage the class/package name.
265: *
266: * @return The fully qualified package/class name.
267: */
268: protected String buildJavaName(final String packageName,
269: final String newPackage) {
270: if (packageName.length() == 0) {
271: return newPackage;
272: } else {
273: return packageName + "." + newPackage;
274: }
275: }
276:
277: /**
278: * Returns the list of classes as an array.
279: *
280: * @return The list of classes.
281: */
282: public Class[] getClasses() {
283: return (Class[]) this .fileList.toArray(new Class[0]);
284: }
285:
286: }
|