/*
* 04/21/2012
*
* Copyright (C) 2010 Robert Futrell
* robert_futrell at users.sourceforge.net
* http://fifesoft.com/rsyntaxtextarea
*
* This library is distributed under a modified BSD license. See the included
* RSTALanguageSupport.License.txt file for details.
*/
package org.fife.rsta.ac.java.buildpath;
import java.io.File;
import java.io.IOException;
import java.util.TreeMap;
import org.fife.rsta.ac.java.Util;
import org.fife.rsta.ac.java.classreader.ClassFile;
/**
* Information about a folder containing a set of classes to add to the "build
* path." This type of library info could be used, for example, to add sibling
* projects in a workspace, not yet built into jars, to another project's build
* path.
*
* @author Robert Futrell
* @version 1.0
* @see JarLibraryInfo
* @see ClasspathLibraryInfo
*/
public class DirLibraryInfo extends LibraryInfo {
private File dir;
public DirLibraryInfo(File dir) {
this(dir, null);
}
public DirLibraryInfo(String dir) {
this(new File(dir));
}
public DirLibraryInfo(File dir, SourceLocation sourceLoc) {
setDirectory(dir);
setSourceLocation(sourceLoc);
}
public DirLibraryInfo(String dir, SourceLocation sourceLoc) {
this(new File(dir), sourceLoc);
}
/**
* Compares this <code>LibraryInfo</code> to another one. Two instances of
* this class are only considered equal if they represent the same class
* file location. Source attachment is irrelevant.
*
* @return The sort order of these two library infos.
*/
public int compareTo(Object o) {
if (o==this) {
return 0;
}
int result = -1;
if (o instanceof DirLibraryInfo) {
return dir.compareTo(((DirLibraryInfo)o).dir);
}
return result;
}
public ClassFile createClassFile(String entryName) throws IOException {
File file = new File(dir, entryName);
if (!file.isFile()) {
System.err.println("ERROR: Invalid class file: " + file.getAbsolutePath());
return null;
}
return new ClassFile(file);
}
public TreeMap createPackageMap() throws IOException {
TreeMap map = new TreeMap();
getPackageMapImpl(dir, null, map);
return map;
}
public long getLastModified() {
return dir.lastModified();
}
public String getLocationAsString() {
return dir.getAbsolutePath();
}
/**
* Does the dirty-work of finding all class files in a directory tree.
*
* @param dir The directory to scan.
* @param pkg The package name scanned so far, in the form
* "<code>com/company/pkgname</code>"...
* @throws IOException If an IO error occurs.
*/
private void getPackageMapImpl(File dir, String pkg, TreeMap retVal)
throws IOException {
File[] children = dir.listFiles();
TreeMap m = retVal;
boolean firstTimeThrough = true;
for (int i=0; i<children.length; i++) {
File child = children[i];
if (child.isFile() && child.getName().endsWith(".class")) {
if (pkg!=null) { // will be null the first time through
if (firstTimeThrough) { // Lazily drill down to pkg map node
firstTimeThrough = false;
String[] items = Util.splitOnChar(pkg, '/');
for (int j=0; j<items.length; j++) {
Object temp = m.get(items[j]);
if (temp instanceof TreeMap) {
m = (TreeMap)temp;
}
else if (temp==null) {
TreeMap submap = new TreeMap();
m.put(items[j], submap);
m = submap;
}
else { // e.g. a ClassFile
// A class with the same name as a package
// name - very unlikely, but could happen. In
// this case, all peer classes/directories will
// share this package/class name conflict, so
// might as well bail now.
return;
}
}
}
}
String className = child.getName().
substring(0, child.getName().length()-6);
m.put(className, null);
}
else if (child.isDirectory()) {
String subpkg = pkg==null ? child.getName() :
(pkg + "/" + child.getName());
getPackageMapImpl(child, subpkg, retVal);
}
}
}
public int hashCode() {
return dir.hashCode();
}
/**
* Sets the directory containing the classes.
*
* @param dir The directory. This cannot be <code>null</code>.
*/
private void setDirectory(File dir) {
if (dir==null || !dir.isDirectory()) {
String name = dir==null ? "null" : dir.getAbsolutePath();
throw new IllegalArgumentException("Directory does not exist: " + name);
}
this.dir = dir;
}
/**
* Returns a string representation of this jar information. Useful for
* debugging.
*
* @return A string representation of this object.
*/
public String toString() {
return "[DirLibraryInfo: " +
"jar=" + dir.getAbsolutePath() +
"; source=" + getSourceLocation() +
"]";
}
}