Skip to content

Commit

Permalink
Added methods to handle making URIs relative to another URI. Improved…
Browse files Browse the repository at this point in the history
… SARIF production to better deal with rules and artifact information. SARIF files now work on commonly avviable viewers.
  • Loading branch information
david-waltermire committed Jun 20, 2024
1 parent 08982f6 commit 62860ed
Show file tree
Hide file tree
Showing 11 changed files with 564 additions and 266 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,14 @@ public class CLIProcessor {
SHOW_STACK_TRACE_OPTION,
VERSION_OPTION);

public static final String COMMAND_VERSION = "http://csrc.nist.gov/ns/metaschema-java/cli/command-version";

@NonNull
private final List<ICommand> commands = new LinkedList<>();
@NonNull
private final String exec;
@NonNull
private final List<IVersionInfo> versionInfos;
private final Map<String, IVersionInfo> versionInfos;

public static void main(String... args) {
System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");
Expand All @@ -130,10 +132,10 @@ public static void main(String... args) {

@SuppressWarnings("null")
public CLIProcessor(@NonNull String exec) {
this(exec, List.of());
this(exec, Map.of());
}

public CLIProcessor(@NonNull String exec, @NonNull List<IVersionInfo> versionInfos) {
public CLIProcessor(@NonNull String exec, @NonNull Map<String, IVersionInfo> versionInfos) {
this.exec = exec;
this.versionInfos = versionInfos;
AnsiConsole.systemInstall();
Expand All @@ -155,7 +157,7 @@ public String getExec() {
* @return the versionInfo
*/
@NonNull
public List<IVersionInfo> getVersionInfos() {
public Map<String, IVersionInfo> getVersionInfos() {
return versionInfos;
}

Expand Down Expand Up @@ -207,7 +209,6 @@ private static void handleNoColor() {
AnsiConsole.systemUninstall();
}

@SuppressWarnings("resource")
public static void handleQuiet() {
LoggerContext ctx = (LoggerContext) LogManager.getContext(false); // NOPMD not closable here
Configuration config = ctx.getConfiguration();
Expand All @@ -221,7 +222,7 @@ public static void handleQuiet() {

protected void showVersion() {
@SuppressWarnings("resource") PrintStream out = AnsiConsole.out(); // NOPMD - not owner
getVersionInfos().stream().forEach(info -> {
getVersionInfos().values().stream().forEach(info -> {
out.println(ansi()
.bold().a(info.getName()).boldOff()
.a(" ")
Expand Down Expand Up @@ -309,6 +310,11 @@ public CallingContext(@NonNull List<String> args) {
this.extraArgs = extraArgs;
}

@NonNull
public CLIProcessor getCLIProcessor() {
return CLIProcessor.this;
}

@Nullable
public ICommand getTargetCommand() {
return calledCommands.peekLast();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@
import gov.nist.secauto.metaschema.core.model.IFlagDefinition;
import gov.nist.secauto.metaschema.core.model.IFlagInstance;

import java.net.URI;

import edu.umd.cs.findbugs.annotations.NonNull;

/**
Expand Down Expand Up @@ -72,11 +70,6 @@ public IFlagInstance getInstance() {
return parent;
}

@Override
public URI getBaseUri() {
return getDefinition().getContainingModule().getLocation();
}

@Override
public String toString() {
StringBuilder builder = new StringBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,9 @@ public Level getSeverity() {
return severity;
}

@SuppressWarnings("null")
@Override
public @NonNull URI getDocumentUri() {
return getNode().getBaseUri();
public URI getDocumentUri() {
return getTarget().getBaseUri();
}

@NonNull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ public void handleAllowedValuesViolation(
public void handleIndexDuplicateViolation(IIndexConstraint constraint, INodeItem node) {
addFinding(ConstraintValidationFinding.builder(constraint, node)
.kind(Kind.FAIL)
.target(node)
.message(newIndexDuplicateViolationMessage(constraint, node))
.severity(Level.CRITICAL)
.build());
Expand All @@ -245,6 +246,7 @@ public void handleIndexMiss(IIndexHasKeyConstraint constraint, INodeItem node, I
addFinding(ConstraintValidationFinding.builder(constraint, node)
.severity(constraint.getLevel())
.kind(toKind(constraint.getLevel()))
.target(target)
.message(newIndexMissMessage(constraint, node, target, key))
.build());
}
Expand All @@ -255,13 +257,15 @@ public void handleGenericValidationViolation(IConstraint constraint, INodeItem n
addFinding(ConstraintValidationFinding.builder(constraint, node)
.severity(constraint.getLevel())
.kind(toKind(constraint.getLevel()))
.target(target)
.message(newGenericValidationViolationMessage(constraint, node, target, message))
.build());
}

@Override
public void handlePass(IConstraint constraint, INodeItem node, INodeItem target) {
addFinding(ConstraintValidationFinding.builder(constraint, node)
.target(target)
.severity(Level.NONE)
.kind(Kind.PASS)
.build());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ enum Kind {
/**
* Get the document's URI.
*
* @return the document's URI
* @return the document's URI or {@code null} if it is not known
*/
@NonNull
@Nullable
URI getDocumentUri();

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,15 @@
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Objects;
import java.util.regex.Pattern;

import edu.umd.cs.findbugs.annotations.NonNull;

public final class UriUtils {
private static final Pattern URI_SEPERATOR_PATTERN = Pattern.compile("\\/");
private static final String URI_SEPERATOR = "/";

private UriUtils() {
// disable construction
Expand Down Expand Up @@ -71,4 +76,92 @@ public static URI toUri(@NonNull String location, @NonNull URI baseUri) throws U
}
return baseUri.resolve(asUri.normalize());
}

/**
* This function extends the functionality of {@link URI#relativize(URI)} by
* supporting relative reference pathing (e.g., ..), when the {@code prepend}
* parameter is set to {@code true}.
*
* @param base
* the URI to relativize against
* @param other
* the URI to make relative
* @param prepend
* if {@code true}, then prepend relative pathing
* @return a new relative URI
* @throws URISyntaxException
* if any of the URIs are malformed
*/
public static URI relativize(URI base, URI other, boolean prepend) throws URISyntaxException {
URI normBase = Objects.requireNonNull(base).normalize();
URI normOther = Objects.requireNonNull(other).normalize();
URI retval = normBase.relativize(normOther);

if (prepend && !normBase.isOpaque() && !retval.isOpaque() && hasSameSchemeAndAuthority(normBase, retval)) {
// the URIs are not opaque and they share the same scheme and authority
String basePath = normBase.getPath();
String targetPath = normOther.getPath();
String newPath = prependRelativePath(basePath, targetPath);

retval = new URI(null, null, newPath, normOther.getQuery(), normOther.getFragment());
}

return retval;
}

private static boolean hasSameSchemeAndAuthority(URI base, URI other) {
String baseScheme = base.getScheme();
boolean retval = (baseScheme == null && other.getScheme() == null)
|| (baseScheme != null && baseScheme.equals(other.getScheme()));
String baseAuthority = base.getAuthority();
retval = retval && ((baseAuthority == null && other.getAuthority() == null)
|| (baseAuthority != null && baseAuthority.equals(other.getAuthority())));
return retval;
}

/**
* Based on code from
* http://stackoverflow.com/questions/10801283/get-relative-path-of-two-uris-in-java
*
* @param base
* the base path to resolve against
* @param target
* the URI to relativize against the base
* @return the relativized URI
*/
public static String prependRelativePath(String base, String target) {

// Split paths into segments
String[] baseSegments = URI_SEPERATOR_PATTERN.split(base);
String[] targetSegments = URI_SEPERATOR_PATTERN.split(target, -1);

// Discard trailing segment of base path, since this resource doesn't matter
if (baseSegments.length > 0 && !base.endsWith(URI_SEPERATOR)) {
baseSegments = Arrays.copyOf(baseSegments, baseSegments.length - 1);
}

// Remove common prefix segments
int segmentIndex = 0;
while (segmentIndex < baseSegments.length && segmentIndex < targetSegments.length
&& baseSegments[segmentIndex].equals(targetSegments[segmentIndex])) {
segmentIndex++;
}

// Construct the relative path
StringBuilder retval = new StringBuilder();
for (int j = 0; j < (baseSegments.length - segmentIndex); j++) {
retval.append("..");
if (retval.length() != 0) {
retval.append(URI_SEPERATOR);
}
}

for (int j = segmentIndex; j < targetSegments.length; j++) {
retval.append(targetSegments[j]);
if (retval.length() != 0 && j < targetSegments.length - 1) {
retval.append(URI_SEPERATOR);
}
}
return retval.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.junit.jupiter.params.provider.MethodSource;

import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
Expand Down Expand Up @@ -61,16 +62,72 @@ private static Stream<Arguments> provideValuesTestToUri() {

@ParameterizedTest
@MethodSource("provideValuesTestToUri")
void testToUri(@NonNull String location, boolean expectedResult) {
void testToUri(@NonNull String location, boolean expectedResult) throws URISyntaxException {
boolean result = INVALID;
Path cwd = Paths.get("");
try {
URI uri = UriUtils.toUri(location, cwd.toAbsolutePath().toUri());
result = VALID;
System.out.println(String.format("%s -> %s", location, uri.toASCIIString()));
} catch (Exception ex) {
ex.printStackTrace();
}
URI uri = UriUtils.toUri(location, cwd.toAbsolutePath().toUri());
result = VALID;
// System.out.println(String.format("%s -> %s", location, uri.toASCIIString()));
assertEquals(result, expectedResult);
}

private static Stream<Arguments> provideArgumentsTestRelativize() {
return Stream.of(
Arguments.of(
"http://example.com/this/file1.txt",
"http://example.com/this/file2.txt",
true,
"file2.txt"),
Arguments.of(
"http://example.com/this",
"http://example.com/this/that",
true,
"that"),
Arguments.of(
"http://example.com/this/",
"http://example.com/this/that",
true,
"that"),
Arguments.of(
"http://example.com/this/that",
"http://example.com/this/new",
true,
"new"),
Arguments.of(
"http://example.com/this/that/A",
"http://example.com/this/new/B",
true,
"../new/B"),
Arguments.of(
"http://example.com/this/that/",
"http://example.com/this/new/",
true,
"../new/"),
Arguments.of(
"http://example.com/this/that/A/",
"http://example.com/this/new/B",
true,
"../../new/B"),
Arguments.of(
"http://example.com/this/that/A/X/file1,text",
"http://example.com/this/that/A/file2.txt",
true,
"../file2.txt"),
Arguments.of(
"http://example.com/this/that/A/",
"http://example.org/this/new/B",
true,
"http://example.org/this/new/B"));
}

@ParameterizedTest
@MethodSource("provideArgumentsTestRelativize")
void testRelativize(@NonNull String uri1, @NonNull String uri2, boolean prepend, @NonNull String expected)
throws URISyntaxException {
URI thisUri = URI.create(uri1);
URI thatUri = URI.create(uri2);

URI result = UriUtils.relativize(thisUri, thatUri, prepend);
assertEquals(expected, result.toASCIIString());
}
}
Loading

0 comments on commit 62860ed

Please sign in to comment.