/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package br.uff.ic.oceano.core.tools.revision;
import br.uff.ic.oceano.core.model.Revision;
import br.uff.ic.oceano.core.model.transiente.Language;
import br.uff.ic.oceano.core.tools.vcs.VCSUtil;
import br.uff.ic.oceano.core.tools.maven.MavenUtil;
import br.uff.ic.oceano.util.file.FileUtils;
import br.uff.ic.oceano.util.file.PathUtil;
import br.uff.ic.oceano.util.SystemUtil;
import br.uff.ic.oceano.ostra.controle.Constantes;
import static br.uff.ic.oceano.ostra.controle.Constantes.DOT_JAVA;
import br.uff.ic.oceano.ostra.model.Item;
import br.uff.ic.oceano.ostra.model.VersionedItem;
import java.io.File;
import java.util.*;
import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.JavaClass;
/**
*
* @author DanCastellani TODO Define Interface and create RevisionUtil
* implementation for each supported language
*/
public class JavaRevisionTool extends AbstractRevisionTool implements RevisionTool {
public JavaRevisionTool() {
}
public void validate(Revision revision) throws Exception {
if (revision == null) {
throw new Exception("Revision is null");
} else if (revision.getProject() == null) {
throw new Exception("Revision project is null");
}
Language lang = revision.getProject().getLanguage();
if (!lang.equals(Language.JAVA)) {
throw new Exception("Unsupported language: " + lang);
}
if (!revision.getProject().isMavenProject()) {
throw new Exception("Only Maven projects are supported");
}
}
/**
* Return absolute source files paths. Ignores files on VCS path or which
* contains Maven test folder pattern.
*
* @param revision
* @return files string paths
* @throws Exception
*/
public Set<String> getSourceFiles(Revision revision) throws Exception {
validate(revision);
Set<String> pathsForSourceFiles = new HashSet<String>();
for (String classPath : getSourceClassPaths(revision)) {
File fileBuffer = new File(classPath);
for (String filePath : FileUtils.getAllFilesInFolderAndSubFolders(fileBuffer, Constantes.DOT_JAVA)) {
fileBuffer = new File(filePath);
if (!fileBuffer.exists()
|| VCSUtil.isVCSpath(filePath)
|| filePath.contains(MavenUtil.MAVEN2_BASE_TEST_FOLDER)) {
continue;
}
if (!fileBuffer.isAbsolute()) {
filePath = PathUtil.getAbsolutePathFromRelativetoCurrentPath(filePath);
}
pathsForSourceFiles.add(filePath);
}
}
return pathsForSourceFiles;
}
/**
*
* @param revision
* @return
* @throws Exception
*/
public Set<VersionedItem> getSourceFilesFromChangedFiles(Revision revision) throws Exception {
validate(revision);
Set<VersionedItem> dotJavaFiles = new HashSet<VersionedItem>();
if (revision.getChangedFiles() == null) {
return dotJavaFiles;
}
for (VersionedItem changedFile : revision.getChangedFiles()) {
String absolutePath = PathUtil.getWellFormedPath(changedFile.getItem().getPath());
if (!isJavaFilePath(absolutePath) //not java file
|| absolutePath.contains(MavenUtil.MAVEN2_BASE_MAIN_SOURCE_FILES) //ignores test packages
) {
continue;
}
dotJavaFiles.add(changedFile);
}
return dotJavaFiles;
}
/**
* //TODO return package with dot as separator
*
* @param revision
* @return
* @throws Exception
*/
public Set<String> getPackages(Revision revision) throws Exception {
validate(revision);
Set<String> packages = new HashSet<String>();
for (String filePath : getSourceFiles(revision)) {
if (isJavaFilePath(filePath)) {
//get the package of this file
packages.add(filePath.substring(0, filePath.lastIndexOf(SystemUtil.FILESEPARATOR)));
}
}
return packages;
}
/**
*
* @param revision
* @return
* @throws Exception
*/
public Set<VersionedItem> getPackagesFromChangedFiles(Revision revision) throws Exception {
validate(revision);
Set<VersionedItem> packages = new HashSet<VersionedItem>();
//its still empty
if (revision.getChangedFiles() == null) {
return packages;
}
for (VersionedItem changedFile : revision.getChangedFiles()) {
//to garantee that every \ or / is changed for the OS-SLASH
final String filePath = PathUtil.getWellFormedPath(changedFile.getItem().getPath());
//we consider only src/main/java classes
if (!filePath.contains(MavenUtil.MAVEN2_BASE_MAIN_SOURCE_FILES)) {
continue;
}
if (isJavaFilePath(filePath)) {
//get the package of this file
VersionedItem changedFilePackage = new VersionedItem();
changedFilePackage.setType(changedFile.getType());
changedFilePackage.setRevision(revision);
Item i = new Item();
i.setPath(filePath.substring(0, filePath.lastIndexOf(SystemUtil.FILESEPARATOR)));
changedFilePackage.setItem(i);
packages.add(changedFilePackage);
}
}
return packages;
}
/**
* Return path of compilation. Example: ...\target. Only for MAVEN projects.
* In case of subprojects, there will be several results.
*
* @param revision
* @return
*/
public Set<String> getCompilationFolders(Revision revision) throws Exception {
if (!revision.getProject().isMavenProject()) {
throw new Exception("Not a maven project");
}
validate(revision);
final String fileSeparator = SystemUtil.FILESEPARATOR;
String pathclasses = revision.getLocalPath();
if (!pathclasses.endsWith(fileSeparator)) {
pathclasses = pathclasses.concat(fileSeparator);
}
File file = new File(pathclasses);
if (!file.isAbsolute()) {
pathclasses = PathUtil.getAbsolutePathFromRelativetoCurrentPath(pathclasses);
file = new File(pathclasses);
}
List<String> folderNames = FileUtils.getAllFoldersAndSubFoldersEndsWith(file, MavenUtil.MAVEN2_BASE_COMPILED_FILES);
if (folderNames == null) {
throw new Exception("No folders found");
}
return new HashSet<String>(folderNames);
}
/**
* Return absolute source class paths. Ignores files on VCS path or which
* contains Maven test folder pattern.
*
* @param revision
* @return
*/
@Override
public Set<String> getSourceClassPaths(Revision revision) throws Exception {
validate(revision);
File revisionPath = new File(revision.getLocalPath());
Set<String> sourcePaths = new HashSet<String>();
for (String possibleSourcePath : FileUtils.getAllFoldersAndSubFoldersContains(revisionPath, MavenUtil.MAVEN2_BASE_MAIN_SOURCE_FILES)) {
File file = new File(possibleSourcePath);
if (!file.exists()
|| VCSUtil.isVCSpath(possibleSourcePath)
|| possibleSourcePath.contains(MavenUtil.MAVEN2_BASE_TEST_FOLDER)) {
continue;
}
if (!file.isAbsolute()) {
possibleSourcePath = PathUtil.getAbsolutePathFromRelativetoCurrentPath(possibleSourcePath);
}
sourcePaths.add(possibleSourcePath);
}
return sourcePaths;
}
/**
* Return absolute path of main source files of a project revision.
*
* @param revision
* @return
* @throws Exception
*/
public String getMainSourcePath(Revision revision) throws Exception {
validate(revision);
File revisionPath = new File(revision.getLocalPath());
List<String> sourcePaths = FileUtils.getAllFoldersAndSubFoldersEndsWith(revisionPath, MavenUtil.MAVEN2_BASE_MAIN_SOURCE_FILES);
if (sourcePaths == null || sourcePaths.isEmpty()) {
return null;
} else if (sourcePaths.size() > 1) {
throw new Exception("Oversized result found");
}
String possibleSourcePath = sourcePaths.get(0);
File file = new File(possibleSourcePath);
if (!file.exists()) {
throw new Exception("Directory '" + possibleSourcePath + "' does not exist");
} else if (VCSUtil.isVCSpath(possibleSourcePath)) {
throw new Exception("Directory '" + possibleSourcePath + "' is from VCS");
} else if (possibleSourcePath.contains(MavenUtil.MAVEN2_BASE_TEST_FOLDER)) {
throw new Exception("Directory '" + possibleSourcePath + "' is from test classes");
}
if (!file.isAbsolute()) {
possibleSourcePath = PathUtil.getAbsolutePathFromRelativetoCurrentPath(possibleSourcePath);
}
return possibleSourcePath;
}
public String getMainCompilationFolder(Revision revision) throws Exception {
validate(revision);
File revisionPath = new File(revision.getLocalPath());
List<String> sourcePaths = FileUtils.getAllFoldersAndSubFoldersEndsWith(revisionPath, MavenUtil.MAVEN2_BASE_COMPILED_FILES);
if (sourcePaths == null || sourcePaths.isEmpty()) {
return null;
} else if (sourcePaths.size() > 1) {
throw new Exception("Oversized result found");
}
String possibleSourcePath = sourcePaths.get(0);
File file = new File(possibleSourcePath);
if (!file.exists()) {
throw new Exception("Directory '" + possibleSourcePath + "' does not exist");
} else if (VCSUtil.isVCSpath(possibleSourcePath)) {
throw new Exception("Directory '" + possibleSourcePath + "' is from VCS");
} else if (possibleSourcePath.contains(MavenUtil.MAVEN2_BASE_TEST_FOLDER)) {
throw new Exception("Directory '" + possibleSourcePath + "' is from test classes");
}
if (!file.isAbsolute()) {
possibleSourcePath = PathUtil.getAbsolutePathFromRelativetoCurrentPath(possibleSourcePath);
}
return possibleSourcePath;
}
/**
*
* @param revision
* @return
* @throws Exception
*/
public List<String> getCompiledClassNames(Revision revision) throws Exception {
validate(revision);
final Set<String> fileNames = getPathsFromCompiledJavaClasses(revision);
List<String> classNames = new LinkedList();
for (String filePath : fileNames) {
ClassParser cp = new ClassParser(filePath);
JavaClass jc = cp.parse();
classNames.add(jc.getClassName());
}
return classNames;
}
/**
*
* @param revision
* @return
* @throws Exception
*/
public Set<String> getPathsFromCompiledJavaClasses(Revision revision) throws Exception {
validate(revision);
Set<String> pathsForCompiledClasses = new HashSet<String>();
for (String aClassPath : getCompilationFolders(revision)) {
final File revisionPath = new File(aClassPath);
pathsForCompiledClasses.addAll(FileUtils.getAllFilesInFolderAndSubFolders(revisionPath, Constantes.DOT_CLASS));
}
return pathsForCompiledClasses;
}
private boolean isJavaFilePath(String path) {
return path.endsWith(DOT_JAVA);
}
}