blob: 5eaaf36bb04c05fcbdac951de87c14c07aa1835a [file] [log] [blame]
package org.eclipse.jdt.internal.ui.wizards;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IPackageDeclaration;
import org.eclipse.jdt.core.JavaConventions;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.util.IClassFileReader;
import org.eclipse.jdt.ui.PreferenceConstants;
/**
*/
public class ClassPathDetector implements IResourceVisitor {
private HashMap fSourceFolders;
private List fClassFiles;
private HashSet fJARFiles;
private IProject fProject;
private IPath fResultOutputFolder;
private IClasspathEntry[] fResultClasspath;
public ClassPathDetector(IProject project) throws CoreException {
fSourceFolders= new HashMap();
fJARFiles= new HashSet(10);
fClassFiles= new ArrayList(100);
fProject= project;
project.accept(this);
fResultClasspath= null;
fResultOutputFolder= null;
detectClasspath();
}
private boolean isNested(IPath path, Iterator iter) {
while (iter.hasNext()) {
IPath other= (IPath) iter.next();
if (other.isPrefixOf(path)) {
return true;
}
}
return false;
}
/**
* Method detectClasspath.
*/
private void detectClasspath() {
ArrayList cpEntries= new ArrayList();
detectSourceFolders(cpEntries);
IPath outputLocation= detectOutputFolder(cpEntries);
detectLibraries(cpEntries, outputLocation);
if (cpEntries.isEmpty()) {
return;
}
IClasspathEntry[] jreEntries= PreferenceConstants.getDefaultJRELibrary();
for (int i= 0; i < jreEntries.length; i++) {
cpEntries.add(jreEntries[i]);
}
IClasspathEntry[] entries= (IClasspathEntry[]) cpEntries.toArray(new IClasspathEntry[cpEntries.size()]);
if (!JavaConventions.validateClasspath(JavaCore.create(fProject), entries, outputLocation).isOK()) {
return;
}
fResultClasspath= entries;
fResultOutputFolder= outputLocation;
}
private IPath findInSourceFolders(IPath path) {
Iterator iter= fSourceFolders.keySet().iterator();
while (iter.hasNext()) {
Object key= iter.next();
List cus= (List) fSourceFolders.get(key);
if (cus.contains(path)) {
return (IPath) key;
}
}
return null;
}
private IPath detectOutputFolder(List entries) {
HashSet classFolders= new HashSet();
for (Iterator iter= fClassFiles.iterator(); iter.hasNext();) {
IFile file= (IFile) iter.next();
IClassFileReader reader= ToolFactory.createDefaultClassFileReader(file.getLocation().toOSString(), IClassFileReader.CLASSFILE_ATTRIBUTES);
char[] className= reader.getClassName();
char[] sourceName= reader.getSourceFileAttribute().getSourceFileName();
if (className != null && sourceName != null) {
IPath packPath= file.getParent().getFullPath();
int idx= CharOperation.lastIndexOf('/', className) + 1;
IPath relPath= new Path(new String(className, 0, idx));
IPath cuPath= relPath.append(new String(sourceName));
IPath resPath= null;
if (idx == 0) {
resPath= packPath;
} else {
IPath folderPath= getFolderPath(packPath, relPath);
if (folderPath != null) {
resPath= folderPath;
}
}
if (resPath != null) {
IPath path= findInSourceFolders(cuPath);
if (path != null) {
return resPath;
} else {
classFolders.add(resPath);
}
}
}
}
IPath projPath= fProject.getFullPath();
if (fSourceFolders.size() == 1 && classFolders.isEmpty() && fSourceFolders.get(projPath) != null) {
return projPath;
} else {
IPath path= projPath.append(PreferenceConstants.getPreferenceStore().getString(PreferenceConstants.SRCBIN_BINNAME));
while (classFolders.contains(path)) {
path= new Path(path.toString() + '1');
}
return path;
}
}
private void detectLibraries(ArrayList cpEntries, IPath outputLocation) {
Set sourceFolderSet= fSourceFolders.keySet();
for (Iterator iter= fJARFiles.iterator(); iter.hasNext();) {
IPath path= (IPath) iter.next();
if (isNested(path, sourceFolderSet.iterator())) {
continue;
}
if (outputLocation != null && outputLocation.isPrefixOf(path)) {
continue;
}
IClasspathEntry entry= JavaCore.newLibraryEntry(path, null, null);
cpEntries.add(entry);
}
}
private void detectSourceFolders(ArrayList resEntries) {
Set sourceFolderSet= fSourceFolders.keySet();
for (Iterator iter= sourceFolderSet.iterator(); iter.hasNext();) {
IPath path= (IPath) iter.next();
ArrayList excluded= new ArrayList();
for (Iterator inner= sourceFolderSet.iterator(); inner.hasNext();) {
IPath other= (IPath) inner.next();
if (!path.equals(other) && path.isPrefixOf(other)) {
IPath pathToExclude= other.removeFirstSegments(path.segmentCount()).addTrailingSeparator();
excluded.add(pathToExclude);
}
}
IPath[] excludedPaths= (IPath[]) excluded.toArray(new IPath[excluded.size()]);
IClasspathEntry entry= JavaCore.newSourceEntry(path, excludedPaths);
resEntries.add(entry);
}
}
private void visitCompilationUnit(IFile file) throws JavaModelException {
ICompilationUnit cu= JavaCore.createCompilationUnitFrom(file);
if (cu != null) {
ICompilationUnit workingCopy= null;
try {
workingCopy= (ICompilationUnit) cu.getWorkingCopy();
synchronized(workingCopy) {
workingCopy.reconcile();
}
IPath packPath= file.getParent().getFullPath();
IPackageDeclaration[] decls= workingCopy.getPackageDeclarations();
String cuName= file.getName();
if (decls.length == 0) {
addToMap(fSourceFolders, packPath, new Path(cuName));
} else {
IPath relpath= new Path(decls[0].getElementName().replace('.', '/'));
IPath folderPath= getFolderPath(packPath, relpath);
if (folderPath != null) {
addToMap(fSourceFolders, folderPath, relpath.append(cuName));
}
}
} finally {
if (workingCopy != null) {
workingCopy.destroy();
}
}
}
}
private void addToMap(HashMap map, IPath folderPath, IPath relPath) {
List list= (List) map.get(folderPath);
if (list == null) {
list= new ArrayList(50);
map.put(folderPath, list);
}
list.add(relPath);
}
private IPath getFolderPath(IPath packPath, IPath relpath) {
int remainingSegments= packPath.segmentCount() - relpath.segmentCount();
if (remainingSegments >= 0) {
IPath common= packPath.removeFirstSegments(remainingSegments);
if (common.equals(relpath)) {
return packPath.uptoSegment(remainingSegments);
}
}
return null;
}
public boolean visit(IResource resource) throws CoreException {
if (resource.getType() == IResource.FILE) {
IFile file= (IFile) resource;
String extension= resource.getFileExtension();
if ("java".equalsIgnoreCase(extension)) { //$NON-NLS-1$
visitCompilationUnit(file);
} else if ("class".equalsIgnoreCase(extension)) { //$NON-NLS-1$
fClassFiles.add(file);
} else if ("jar".equalsIgnoreCase(extension)) { //$NON-NLS-1$
fJARFiles.add(file.getFullPath());
}
return false;
}
return true;
}
public IPath getOutputLocation() {
return fResultOutputFolder;
}
public IClasspathEntry[] getClasspath() {
return fResultClasspath;
}
}