/*
* MicroJIAC - A Lightweight Agent Framework
* This file is part of MicroJIAC MIDlet-Maven-Plugin.
*
* Copyright (c) 2007-2012 DAI-Labor, Technische Universität Berlin
*
* This library includes software developed at DAI-Labor, Technische
* Universität Berlin (http://www.dai-labor.de)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
/*
* $Id$
*/
package de.jiac.micro.reflect;
import java.io.File;
import java.util.*;
/**
* This enumerator browses through the given class directory tree and loads all classes this structure contains.
*
* @author Marcel Patzlaff
* @version $Revision$
*/
public class DirectoryClassEnumerator implements Enumeration {
// Enumeration<Class> {
/**
* Utility class that allows us to walk through the folder
* structure without recursion.
*/
protected class ClassFolder {
private ClassFolder _parent;
private File _file;
private String _package;
private Enumeration<File> _files;
private Enumeration<ClassFolder> _folders;
public ClassFolder(File file) {
this(null, file);
}
public ClassFolder(ClassFolder parent, File file) {
_parent = parent;
_file = file;
initialise();
}
public void initialise() {
File[] children= _file.listFiles();
List<File> classFiles= new ArrayList<File>();
List<ClassFolder> folders= new ArrayList<ClassFolder>();
for(File child : children) {
if(child.isDirectory()) {
folders.add(new ClassFolder(this, child));
} else if(child.getName().endsWith(ClassCollector.CLASS_SUFFIX)){
classFiles.add(child);
}
}
_files= Collections.enumeration(classFiles);
_folders= Collections.enumeration(folders);
}
public ClassFolder getParent() {
return _parent;
}
public String getPackage() {
if (_package == null) {
StringBuilder builder = new StringBuilder();
insertPackage(builder);
_package = builder.toString();
}
return _package;
}
public Enumeration<ClassFolder> getFolders() {
return _folders;
}
public Enumeration<File> getFiles() {
return _files;
}
protected void insertPackage(StringBuilder builder) {
if (_parent != null) {
_parent.insertPackage(builder);
if(builder.length() > 0) {
builder.append('.');
}
builder.append(_file.getName());
}
}
}
private File _root;
private ClassLoader _loader;
private ClassFolder _currentFolder;
private Class _current;
public DirectoryClassEnumerator(File rootFolder, ClassLoader loader) {
if(!rootFolder.exists() || !rootFolder.isDirectory()) {
throw new IllegalArgumentException("rootFolder have to be an existing directory");
}
_root = rootFolder;
_loader = loader;
}
public boolean hasMoreElements() {
if (_current != null) {
return true;
}
return loadNext();
}
public Class nextElement() {
if (!hasMoreElements()) {
throw new NoSuchElementException("DirectoryClassEnumerator");
}
try {
return _current;
} finally {
_current = null;
}
}
private boolean loadNext() {
if(_root == null) {
return false;
}
if(_currentFolder == null) {
_currentFolder= new ClassFolder(_root);
}
while(_currentFolder.getFiles().hasMoreElements() || _currentFolder.getFolders().hasMoreElements() || _currentFolder.getParent() != null) {
while(_currentFolder.getFiles().hasMoreElements()) {
File classFile= _currentFolder.getFiles().nextElement();
String fileName= classFile.getName();
fileName= fileName.substring(0, fileName.length() - ClassCollector.CLASS_SUFFIX.length());
String packageName= _currentFolder.getPackage();
String className= packageName.length() > 0 ? packageName + '.' + fileName : fileName;
try {
_current= Class.forName(className, false, _loader);
return true;
} catch (Exception e) {
// fall through
}
}
if(_currentFolder.getFolders().hasMoreElements()) {
_currentFolder= _currentFolder.getFolders().nextElement();
} else if(_currentFolder.getParent() != null){
_currentFolder= _currentFolder.getParent();
} else {
break;
}
}
_root= null;
return false;
}
}