com.seeq.utilities.process.SQCommand Maven / Gradle / Ivy
The newest version!
package com.seeq.utilities.process;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
/**
* Utility for creating processes to call "sq" commands, such as "sq run" and "sq db start". These can be run only in
* development or testing, not in production! If you need to run "seeq" commands such as "seeq start" or "seeq diag"
* in production, use {@link PilotCommand}.
*/
@Slf4j
@UtilityClass
public class SQCommand {
/**
* Creates a process spawn object whose directory is set to the location of the "nearest" sq file (moving upwards
* toward the root of the repo)
*
* @param command
* a string array containing an sq command ie {"database", "--scheme", "test"}
* @param callingClass
* the class object for the class that is calling the command. this is used to properly locate the sq
* command in a parent folder.
* @return a ProcessSpawn object
*/
public static ProcessSpawn createProcessSpawn(String[] command, Class> callingClass) {
File sqFile = findSqFile(callingClass);
return createProcessSpawn(command, sqFile);
}
/**
* Creates a process spawn object whose directory is set to an explicit "sq" file location.
*
* @param command
* a string array containing an sq command ie {"database", "--scheme", "test"}
* @param sqFile
* an explicit "sq" file location. This can be used to call "sq" commands across the boundaries of
* directories / Maven modules. Use with caution!
* @return a ProcessSpawn object
*/
public static ProcessSpawn createProcessSpawn(String[] command, File sqFile) {
List commandList = new ArrayList<>();
if (OperatingSystem.isWindows()) {
commandList.add(".\\sq.bat");
} else {
commandList.add("./sq");
}
commandList.addAll(Arrays.asList(command));
ProcessSpawn sqProcess = new ProcessSpawn(commandList);
sqProcess.directory(sqFile.getParentFile());
sqProcess.setUseCmdShell(true);
return sqProcess;
}
public static File findSqFile(Class> callingClass) {
String fileName = "sq";
// the preferred way to find the proper sq executable is to walk up the directory structure from the given
// calling class
File fileOfCurrentClass = new File(callingClass.getProtectionDomain().getCodeSource().getLocation()
.getFile());
File folderOfCurrentClass = new File(fileOfCurrentClass.getParent());
File sqFile = findRoot(folderOfCurrentClass, fileName);
if (sqFile == null) {
LOG.debug("no {} found in {} Trying {} instead.", fileName, fileOfCurrentClass,
System.getProperty("user.dir"));
/* maybe the calling class was outside the folder structure of the tree that has sq? This can happen if the
* calling class was pulled from a jar in the repository (eg ~/.m2/repository/com/seeq/something ) This is
* known to happen on (at least) osx when invoking "mvn verify" inside appserver/driver/graph.
*
* This fallback tries the current directory of the parent process and search again for the command. If this
* fails, it isn't graceful about trying something else. Oh well, it's not any worse than it was. */
folderOfCurrentClass = new File(System.getProperty("user.dir"));
sqFile = findRoot(folderOfCurrentClass, fileName);
}
return sqFile;
}
/**
* Recursively looks for a file in a given folder and its parent folders
*
* @param folder
* a File object with a directory to start the search
* @param fileName
* the name of the file being searched for
* @return File of the folder that contains the fileName
*/
private static File findRoot(File folder, String fileName) {
final File fileEntry = new File(folder, fileName);
if (fileEntry.isFile()) {
return fileEntry;
} else if (folder.getParentFile() != null) {
return findRoot(folder.getParentFile(), fileName);
} else {
return null;
}
}
}