/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.codeigniter.netbeans.shared;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.spi.project.support.ant.AntProjectHelper;
import org.netbeans.spi.project.support.ant.EditableProperties;
import org.netbeans.spi.project.support.ant.PropertyUtils;
import org.openide.filesystems.FileObject;
import org.openide.util.Exceptions;
import org.openide.util.Mutex;
/**
*
* @author dwoods
*
* This class is designed to contain functions for searching for files on the File System, and other file related functions
*
*/
public abstract class FileExtractor {
public static final String INCLUDE_PATH = "include.path";
public static final String VIEW_PATH = "application/views/";
public static final String MODEL_PATH = "application/models/";
public static final String CONTROLLER_PATH = "application/controllers/";
private static final String[] APP_BASE
= {"cache", "config", "controllers", "core", "helpers", "models"};
/**
*
* @param dir - The directory to be searched
* @param fileExts - The list of valid file extensions for the files to be returned. The "." should not be included
* Pass null to return all files in the directory
* @param recursive - Whether to search the directory recursively (will search all directories within the given directory)
* @return - A List of File's matching the given file extensions
*/
public static List<File> getFilesFromDirectory(File dir, List<String> fileExts, boolean recursive) throws IllegalArgumentException, IOException
{
if (!dir.isDirectory()) {
throw new IllegalArgumentException(String.format("%s is not a directory\n", dir.getAbsolutePath()));
}
List<File> retval = new LinkedList<File>();
// Use a DirectoryStream to iterate over files in the directory
// since JavaDoc recommends it for its efficiency over other methods
DirectoryStream<Path> dirStream = Files.newDirectoryStream(dir.toPath());
Iterator<Path> it = dirStream.iterator();
while (it.hasNext()) {
File nextFile = it.next().toFile();
if (nextFile.isDirectory() && recursive) {
try {
retval.addAll(getFilesFromDirectory(nextFile, fileExts, recursive));
}
catch (IllegalArgumentException iae) {
System.err.println("Illegal Argument: Something went terribly wrong in getFilesFromDirectory()!");
}
catch (IOException ioe) {
System.err.printf("getFilesFromDirectory(): Unable to get files from %s\n", nextFile.getAbsolutePath());
}
}
else if (nextFile.isFile()) {
String ext = getFileExtensionType(nextFile);
if (fileExts == null || fileExts.contains(ext)) {
retval.add(nextFile);
}
}
}
return retval;
}
/**
*
* @param file
* @return - The file's extension (not including the ".") or empty string if file doesn't have an extension.
*/
public static String getFileExtensionType(File file) throws IllegalArgumentException
{
if (file.isDirectory()) {
throw new IllegalArgumentException(String.format("%s is not a file\n", file.getAbsoluteFile()));
}
String retval = "";
int index = file.getName().lastIndexOf(".");
if (index != -1) {
retval = file.getName().substring(index + 1);
}
return retval;
}
/**
*
* @param file
* @return True if the file extension is ".php"
*/
public static boolean isPHPFile(File file) {
boolean retval = false;
try {
retval = getFileExtensionType(file).equals("php");
}
catch (IllegalArgumentException iae) {
// Do nothing... will return false
}
return retval;
}
/**
* Get the CodeIgniter Root for any file in application folder
*
* @param doc FileObject document
* @return root
*/
public static FileObject getCiRoot(FileObject doc) {
//TODO: Need Talk
//What is the best way to know the "root" directory of CodeIgniter?
while (doc != null) {
doc = doc.getParent();
FileObject[] children = doc.getChildren();
int count = 0;
for (FileObject child: children) {
for (String folder: APP_BASE) {
if (child
.getName()
.equals(folder.toLowerCase(Locale.ENGLISH))) {
count++;
break;
}
}
}
if (count == APP_BASE.length) {
break;
}
}
if (doc == null) {
return null;
}
FileObject root = doc.getParent();
return root;
}
/**
* Use the current PHp document as a pointer to add
* auto completion file into the project path
* @param doc any document of the current project
*/
public static void addCompleteToIncludePathFromDoc(final FileObject doc) {
FileObject ciRoot = getCiRoot(doc);
if (ciRoot == null) {
return;
}
Project project = FileOwnerQuery.getOwner(ciRoot);
if (project == null) {
return;
}
addCompleteToIncludePath(ciRoot, project);
}
/**
* Add auto completion file into the project path
* @param ciRoot Root of CodeIgniter Project
* @param project the Project object of the PHP Project
*/
public static void addCompleteToIncludePath(
final FileObject ciRoot, final Project project) {
ProjectManager.mutex().writeAccess(new Mutex.Action<Void>() {
@Override
public Void run() {
try {
AntProjectHelper helper = project.getLookup().lookup(AntProjectHelper.class);
if (helper == null) {
return null;
}
EditableProperties properties
= helper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
String currentPaths[]
= PropertyUtils.tokenizePath((properties.getProperty(INCLUDE_PATH)));
ArrayList<String> newPaths
= new ArrayList<String>(Arrays.asList(currentPaths));
for (String path: currentPaths) {
if (path != null) {
if (path.contains("ci_autocomplete")) {
return null;
} else {
newPaths.add(path);
}
}
}
String target = getAutocompleteFolderPath(ciRoot);
newPaths.add(target);
properties.setProperty(
INCLUDE_PATH,
newPaths.toArray(new String[0]));
helper.putProperties(
AntProjectHelper.PROJECT_PROPERTIES_PATH, properties);
ProjectManager.getDefault().saveProject(project);
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
return null;
}
});
}
/**
* Get the auto complete file path.
* @param ciRoot the Root of codeigniter project where path start
* @return path
* @throws IOException
*/
private static String getAutocompleteFolderPath(FileObject ciRoot) throws IOException {
InputStream is = FileExtractor.class.getResourceAsStream(
"/com/codeigniter/netbeans/completer/autocomplete.php");
if (is == null) {
return null;
}
String completionFolderPath = ciRoot.getPath() + "/../ci_autocomplete_folder/";
String completionFilePath = completionFolderPath + "ci_autocomplete.php";
File completionFolder = new File(completionFolderPath);
if (!completionFolder.exists()) {
completionFolder.mkdirs();
}
File completionFile = new File(completionFilePath);
if (!completionFile.exists()) {
completionFile.createNewFile();
}
FileOutputStream os = new FileOutputStream(completionFile, false);
while (is.available() > 0) {
os.write(is.read());
}
is.close();
os.close();
return completionFolder.getPath();
}
}