Skip to content

Commit

Permalink
able to resolve feature files in jar files ref #520
Browse files Browse the repository at this point in the history
  • Loading branch information
ptrthomas committed Sep 8, 2018
1 parent 6ea511d commit ef22ef3
Show file tree
Hide file tree
Showing 27 changed files with 312 additions and 115 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import com.intuit.karate.core.Feature;
import java.io.File;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;

Expand All @@ -38,7 +39,7 @@ public class FeatureContext {
public final String tagSelector;
public final Feature feature;
public final Logger logger;
public final File workingDir;
public final Path parentPath;
public final Map<String, CallResult> callCache;

private static String getEnv(String envString) {
Expand All @@ -55,7 +56,7 @@ public FeatureContext(String envString, Feature feature, File workingDir, String
this.feature = feature;
this.callCache = new HashMap(1);
this.logger = logger;
this.workingDir = workingDir == null ? feature.getFile().getParentFile() : workingDir;
this.parentPath = workingDir == null ? feature.getPath().getParent() : workingDir.toPath();
}

public static FeatureContext forEnv(String env) {
Expand Down
91 changes: 68 additions & 23 deletions karate-core/src/main/java/com/intuit/karate/FileUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ public static ScriptValue readFile(String text, ScenarioContext context) {
String contents = readFileAsString(text, context);
return new ScriptValue(contents, text);
} else if (isFeatureFile(text)) {
FileResource fr = resolvePath(text, context);
Feature feature = FeatureParser.parse(fr.file, fr.relativePath);
Resource fr = resolvePath(text, context);
Feature feature = FeatureParser.parse(fr);
feature.setCallTag(pair.right);
return new ScriptValue(feature, text);
} else if (isYamlFile(text)) {
Expand Down Expand Up @@ -139,13 +139,14 @@ public static Feature resolveFeature(String path) {
return feature;
}

private static FileResource resolvePath(String path, ScenarioContext context) {
private static Resource resolvePath(String path, ScenarioContext context) {
if (isClassPath(path) || isFilePath(path)) {
return new FileResource(fromRelativeClassPath(path), path);
return new Resource(fromRelativeClassPath(path), path);
} else {
try {
File file = new File(context.featureContext.workingDir + File.separator + path);
return new FileResource(file, path);
Path parentPath = context.featureContext.parentPath;
Path childPath = parentPath.resolve(path);
return new Resource(childPath, path);
} catch (Exception e) {
logger.error("feature relative path resolution failed: {}", e.getMessage());
throw e;
Expand All @@ -164,8 +165,8 @@ private static String readFileAsString(String path, ScenarioContext context) {
}

public static InputStream getFileStream(String path, ScenarioContext context) {
FileResource fr = resolvePath(path, context);
return getStream(fr.file);
Resource fr = resolvePath(path, context);
return fr.getStream();
}

private static InputStream getStream(File file) {
Expand Down Expand Up @@ -319,7 +320,7 @@ public static void renameFileIfZeroBytes(String fileName) {

public static String toRelativeClassPath(File file) {
Path path = file.toPath();
for (Path rootPath : getAllClassPaths()) {
for (Path rootPath : getAllClassPaths(null)) {
if (path.startsWith(rootPath)) {
Path relativePath = rootPath.relativize(path);
return CLASSPATH_COLON + relativePath.toString();
Expand Down Expand Up @@ -354,24 +355,26 @@ public static File fromRelativeClassPath(String relativePath) {
}
}

public static List<FileResource> scanForFeatureFilesOnClassPath() {
return scanForFeatureFiles(true, CLASSPATH_COLON);
public static List<Resource> scanForFeatureFilesOnClassPath(ClassLoader cl) {
return scanForFeatureFiles(true, CLASSPATH_COLON, cl);
}

public static List<FileResource> scanForFeatureFiles(List<String> paths) {
List<FileResource> list = new ArrayList();
public static List<Resource> scanForFeatureFiles(List<String> paths, ClassLoader cl) {
List<Resource> list = new ArrayList();
for (String path : paths) {
boolean classpath = isClassPath(path);
list.addAll(scanForFeatureFiles(classpath, path));
list.addAll(scanForFeatureFiles(classpath, path, cl));
}
return list;
}

public static List<Path> getAllClassPaths() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
public static List<Path> getAllClassPaths(ClassLoader classLoader) {
if (classLoader == null) {
classLoader = Thread.currentThread().getContextClassLoader();
}
try {
List<Path> list = new ArrayList();
Enumeration<URL> iterator = cl.getResources("");
Enumeration<URL> iterator = classLoader.getResources("");
while (iterator.hasMoreElements()) {
URL url = iterator.nextElement();
list.add(Paths.get(url.toURI()));
Expand All @@ -382,11 +385,37 @@ public static List<Path> getAllClassPaths() {
}
}

public static List<FileResource> scanForFeatureFiles(boolean classpath, String searchPath) {
List<FileResource> files = new ArrayList();
private static FileSystem getFileSystem(URI uri) {
try {
return FileSystems.getFileSystem(uri);
} catch (Exception e) {
logger.warn("creating file system for URI: {} - {}", uri, e.getMessage());
try {
return FileSystems.newFileSystem(uri, Collections.emptyMap());
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
}

public static List<Resource> scanForFeatureFiles(boolean classpath, String searchPath, ClassLoader cl) {
List<Resource> files = new ArrayList();
if (classpath) {
searchPath = removePrefix(searchPath);
for (Path rootPath : getAllClassPaths()) {
if (cl != null) {
try {
URL url = cl.getResource(searchPath);
if (url != null && url.toURI().getScheme().equals("jar")) {
FileSystem fileSystem = getFileSystem(url.toURI());
Path search = fileSystem.getPath(searchPath);
collectFeatureFiles(search, files);
return files; // exit early
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
for (Path rootPath : getAllClassPaths(cl)) {
collectFeatureFiles(rootPath, searchPath, files);
}
} else {
Expand All @@ -395,7 +424,7 @@ public static List<FileResource> scanForFeatureFiles(boolean classpath, String s
return files;
}

private static void collectFeatureFiles(Path rootPath, String searchPath, List<FileResource> files) {
private static void collectFeatureFiles(Path rootPath, String searchPath, List<Resource> files) {
boolean classpath = rootPath != null;
Path search;
if (classpath) {
Expand All @@ -419,9 +448,25 @@ private static void collectFeatureFiles(Path rootPath, String searchPath, List<F
File file = path.toFile();
Path relativePath = rootPath.relativize(path);
String prefix = classpath ? CLASSPATH_COLON : "";
files.add(new FileResource(file, prefix + relativePath.toString()));
files.add(new Resource(file, prefix + relativePath.toString()));
}
}
}
}

private static void collectFeatureFiles(Path searchPath, List<Resource> files) {
Stream<Path> stream;
try {
stream = Files.walk(searchPath);
} catch (IOException e) {
throw new RuntimeException(e);
}
for (Iterator<Path> paths = stream.iterator(); paths.hasNext();) {
Path path = paths.next();
if (path.getFileName().toString().endsWith(".feature")) {
Resource resource = new Resource(path, CLASSPATH_COLON + path.toString());
files.add(resource);
}
}
}

}
2 changes: 1 addition & 1 deletion karate-core/src/main/java/com/intuit/karate/IdeUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public class IdeUtils {

private static final Pattern COMMAND_NAME = Pattern.compile("--name (.+?\\$)");

public static void main(String[] args) {
public static void exec(String[] args) {
String command = System.getProperty("sun.java.command");
System.out.println("command: " + command);
boolean isIntellij = command.contains("org.jetbrains");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,59 @@
package com.intuit.karate;

import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;

/**
*
* @author pthomas3
*/
public class FileResource {
public class Resource {

private final boolean file;
private final Path path;
private final String relativePath;

public final File file;
public final String relativePath;
public Resource(File file, String relativePath) {
this.file = true;
path = file.toPath();
this.relativePath = relativePath;
}

public FileResource(File file, String relativePath) {
this.file = file;
public Resource(Path path, String relativePath) {
this.path = path;
file = !path.toUri().getScheme().equals("jar");
this.relativePath = relativePath;
}


public String getRelativePath() {
return relativePath;
}

public Path getPath() {
return path;
}

public InputStream getStream() {
try {
return Files.newInputStream(path);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public String getAsString() {
if (file) {
return FileUtils.toString(path.toFile());
} else {
return FileUtils.toString(getStream());
}
}

@Override
public String toString() {
return relativePath;
}

}
6 changes: 1 addition & 5 deletions karate-core/src/main/java/com/intuit/karate/core/Engine.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,7 @@ public static String getFeatureName(Step step) {
if (step.getScenario() == null) {
return UNKNOWN;
}
File file = step.getScenario().getFeature().getFile();
if (file == null) {
return UNKNOWN;
}
return file.getName();
return step.getScenario().getFeature().getPath().getFileName().toString();
}

public static Result executeStep(Step step, Actions actions) {
Expand Down
29 changes: 16 additions & 13 deletions karate-core/src/main/java/com/intuit/karate/core/Feature.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@
package com.intuit.karate.core;

import com.intuit.karate.FileUtils;
import com.intuit.karate.Resource;
import com.intuit.karate.StringUtils;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

Expand All @@ -37,8 +38,7 @@ public class Feature {

public static final String KEYWORD = "Feature";

private final File file;
private final String relativePath;
private final Resource resource;
private final String packageQualifiedName;

private int line;
Expand All @@ -53,10 +53,9 @@ public class Feature {
private String callTag;
private String callName;

public Feature(File file, String relativePath) {
this.file = file;
this.relativePath = relativePath;
this.packageQualifiedName = FileUtils.toPackageQualifiedName(relativePath);
public Feature(Resource resource) {
this.resource = resource;
this.packageQualifiedName = FileUtils.toPackageQualifiedName(resource.getRelativePath());
}

public boolean isBackgroundPresent() {
Expand Down Expand Up @@ -122,8 +121,8 @@ public String getText() {

public void initLines() {
if (lines == null) {
if (file != null) {
lines = StringUtils.toStringLines(FileUtils.toString(file));
if (resource != null) {
lines = StringUtils.toStringLines(resource.toString());
}
}
}
Expand Down Expand Up @@ -172,14 +171,18 @@ public List<String> getLines() {

public void setLines(List<String> lines) {
this.lines = lines;
}
}

public File getFile() {
return file;
public Resource getResource() {
return resource;
}

public Path getPath() {
return resource.getPath();
}

public String getRelativePath() {
return relativePath;
return resource.getRelativePath();
}

public String getPackageQualifiedName() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public FeatureBackend(Feature feature, Map<String, Object> vars) {

public FeatureBackend(Feature feature, Map<String, Object> vars, boolean ssl) {
this.feature = feature;
featureName = feature.getFile().getName();
featureName = feature.getPath().toFile().getName();
this.ssl = ssl;
CallContext callContext = new CallContext(null, false);
FeatureContext featureContext = new FeatureContext(feature, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ public void submit(Runnable next) {

private static ScenarioInfo getScenarioInfo(Scenario scenario, FeatureContext env) {
ScenarioInfo info = new ScenarioInfo();
info.setFeatureDir(env.feature.getFile().getParent());
info.setFeatureFileName(env.feature.getFile().getName());
info.setFeatureDir(env.feature.getPath().getParent().toString());
info.setFeatureFileName(env.feature.getPath().getFileName().toString());
info.setScenarioName(scenario.getName());
info.setScenarioDescription(scenario.getDescription());
info.setScenarioType(scenario.isOutline() ? ScenarioOutline.KEYWORD : Scenario.KEYWORD);
Expand Down
Loading

0 comments on commit ef22ef3

Please sign in to comment.