Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/run-qt3.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,15 @@ jobs:

qt3-jsoniq:
needs: [resolve-baseline, build]
uses: RumbleDB/rumble-test-suite/.github/workflows/qt3-suite.yml@master
uses: RumbleDB/rumble-test-suite/.github/workflows/qt3-suite.yml@AtHint
with:
tested_parser: jsoniq
rumble_artifact_name: rumble-build
baseline_run_id: ${{ needs.resolve-baseline.outputs.baseline_run_id }}

qt3-xquery:
needs: [resolve-baseline, build]
uses: RumbleDB/rumble-test-suite/.github/workflows/qt3-suite.yml@master
uses: RumbleDB/rumble-test-suite/.github/workflows/qt3-suite.yml@AtHint
with:
tested_parser: xquery
rumble_artifact_name: rumble-build
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/rumbledb/compiler/InferTypeVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,7 @@ private boolean tryAnnotateSpecificFunctions(FunctionCallExpression expression,
) {
String path = stringLiteralExpr.getValue();
URI uri = FileSystemUtil.resolveFileSystemURI(
staticContext.getStaticBaseURI(),
staticContext.getStaticBaseURIOrNull(),
path,
expression.getMetadata()
);
Expand Down Expand Up @@ -812,7 +812,7 @@ private boolean tryAnnotateSpecificFunctions(FunctionCallExpression expression,
) {
String path = stringLiteralExpr.getValue();
URI uri = FileSystemUtil.resolveFileSystemURI(
staticContext.getStaticBaseURI(),
staticContext.getStaticBaseURIOrNull(),
path,
expression.getMetadata()
);
Expand Down
20 changes: 13 additions & 7 deletions src/main/java/org/rumbledb/compiler/ModuleImportLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,19 @@ public static LibraryModule load(
CompilationConfiguration compilationConfiguration,
ExceptionMetadata metadata
) {
URI baseURI = importingModuleContext.getStaticBaseURI();
URI namespaceURI = URILiteralUtils.resolve(baseURI, namespace, metadata);
List<String> candidates = locationHints.isEmpty() ? List.of(namespace) : locationHints;
URI baseURI = importingModuleContext.getStaticBaseURIOrNull();
String normalizedNamespace = URILiteralUtils.normalizeAsAnyURI(namespace);
List<String> candidates = locationHints.isEmpty() ? List.of(normalizedNamespace) : locationHints;
Exception lastFailure = null;

for (String candidate : candidates) {
URI location = URILiteralUtils.resolve(baseURI, candidate, metadata);
URI location;
try {
location = URILiteralUtils.resolve(baseURI, candidate, metadata);
} catch (RumbleException e) {
lastFailure = e;
continue;
}
try {
LibraryModule module = VisitorHelpers.parseLibraryModuleFromLocation(
location,
Expand All @@ -48,10 +54,10 @@ public static LibraryModule load(
metadata
);

if (!namespaceURI.toString().equals(module.getNamespace())) {
if (!normalizedNamespace.equals(module.getNamespace())) {
throw new ModuleNotFoundException(
"A module with namespace "
+ namespaceURI
+ normalizedNamespace
+ " was not found. The namespace of the module at this location was: "
+ module.getNamespace(),
metadata
Expand All @@ -66,7 +72,7 @@ public static LibraryModule load(

RumbleException exception = new ModuleNotFoundException(
"Module not found: %s, cause: %s".formatted(
namespaceURI,
normalizedNamespace,
lastFailure != null ? lastFailure.getMessage() : "unknown"
),
metadata
Expand Down
28 changes: 13 additions & 15 deletions src/main/java/org/rumbledb/compiler/TranslationVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -371,24 +371,19 @@ public Node visitProgram(JsoniqParser.ProgramContext ctx) {
@Override
public Node visitLibraryModule(JsoniqParser.LibraryModuleContext ctx) {
String prefix = ctx.ncName().getText();
String namespace = processURILiteral(ctx.uriLiteral());
String namespace = URILiteralUtils.normalizeAsAnyURI(processURILiteral(ctx.uriLiteral()));
if (namespace.equals("")) {
throw new EmptyModuleURIException("Module URI is empty.", createMetadataFromContext(ctx));
}
URI resolvedURI = URILiteralUtils.resolve(
this.moduleContext.getStaticBaseURI(),
namespace,
createMetadataFromContext(ctx)
);
this.libraryModuleNamespace = resolvedURI.toString();
this.libraryModuleNamespace = namespace;
bindNamespace(
prefix,
resolvedURI.toString(),
namespace,
createMetadataFromContext(ctx)
);

Prolog prolog = (Prolog) this.visitProlog(ctx.prolog());
LibraryModule module = new LibraryModule(prolog, resolvedURI.toString(), createMetadataFromContext(ctx));
LibraryModule module = new LibraryModule(prolog, namespace, createMetadataFromContext(ctx));
module.setStaticContext(this.moduleContext);
return module;
}
Expand Down Expand Up @@ -475,12 +470,12 @@ public Node visitProlog(JsoniqParser.PrologContext ctx) {
);
}
String uriString = processURILiteral(setterContext.baseURIDecl().uriLiteral());
URI uri = URILiteralUtils.resolve(
this.moduleContext.getStaticBaseURI(),
URI uri = URILiteralUtils.resolveStaticBaseUri(
this.moduleContext.getStaticBaseURIOrNull(),
uriString,
createMetadataFromContext(setterContext.baseURIDecl())
);
this.moduleContext.setStaticBaseUri(uri);
this.moduleContext.setStaticBaseUri(uri, URILiteralUtils.toStaticBaseUriString(uri, uriString));
baseURISet = true;
continue;
}
Expand Down Expand Up @@ -4054,16 +4049,16 @@ private void processDefaultCollation(DefaultCollationDeclContext ctx) {
private String resolveCollationUri(UriLiteralContext ctx) {
String uriString = processURILiteral(ctx);
URI uri = URILiteralUtils.resolve(
this.moduleContext.getStaticBaseURI(),
this.moduleContext.getStaticBaseURIOrNull(),
uriString,
createMetadataFromContext(ctx)
);
return uri.toString();
}

public LibraryModule processModuleImport(JsoniqParser.ModuleImportContext ctx) {
String namespace = processURILiteral(ctx.targetNamespace);
ExceptionMetadata metadata = createMetadataFromContext(ctx);
String namespace = processURILiteral(ctx.targetNamespace);
if (namespace.isEmpty()) {
throw new EmptyModuleURIException("Module URI is empty.", metadata);
}
Expand All @@ -4076,8 +4071,10 @@ public LibraryModule processModuleImport(JsoniqParser.ModuleImportContext ctx) {
);
}
}
namespace = URILiteralUtils.normalizeAsAnyURI(namespace);
List<String> locationHints = ctx.locations.stream()
.map(this::processURILiteral)
.map(URILiteralUtils::normalizeAsAnyURI)
.collect(Collectors.toList());
LibraryModule libraryModule = ModuleImportLoader.load(
namespace,
Expand All @@ -4097,7 +4094,8 @@ public LibraryModule processModuleImport(JsoniqParser.ModuleImportContext ctx) {
}

public ExceptionMetadata generateMetadata(Token start, Token end) {
return ExceptionMetadata.fromTokens(this.moduleContext.getStaticBaseURI().toString(), start, end, this.code);
String location = this.moduleContext.getStaticBaseUriStringOrNull();
return ExceptionMetadata.fromTokens(location == null ? "unknown" : location, start, end, this.code);
}

private List<Annotation> processAnnotations(JsoniqParser.AnnotationsContext annotations) {
Expand Down
28 changes: 13 additions & 15 deletions src/main/java/org/rumbledb/compiler/XQueryTranslationVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -355,24 +355,19 @@ public Node visitProgram(XQueryParser.ProgramContext ctx) {
@Override
public Node visitLibraryModule(XQueryParser.LibraryModuleContext ctx) {
String prefix = ctx.ncName().getText();
String namespace = processURILiteral(ctx.uriLiteral());
String namespace = URILiteralUtils.normalizeAsAnyURI(processURILiteral(ctx.uriLiteral()));
if (namespace.equals("")) {
throw new EmptyModuleURIException("Module URI is empty.", createMetadataFromContext(ctx));
}
URI resolvedURI = URILiteralUtils.resolve(
this.moduleContext.getStaticBaseURI(),
namespace,
createMetadataFromContext(ctx)
);
this.libraryModuleNamespace = resolvedURI.toString();
this.libraryModuleNamespace = namespace;
bindNamespace(
prefix,
resolvedURI.toString(),
namespace,
createMetadataFromContext(ctx)
);

Prolog prolog = (Prolog) this.visitProlog(ctx.prolog());
LibraryModule module = new LibraryModule(prolog, resolvedURI.toString(), createMetadataFromContext(ctx));
LibraryModule module = new LibraryModule(prolog, namespace, createMetadataFromContext(ctx));
module.setStaticContext(this.moduleContext);
return module;
}
Expand Down Expand Up @@ -569,12 +564,12 @@ private void processPrologPhase1Setter(SetterContext setterContext, PrologPhase1
);
}
String uriString = processURILiteral(setterContext.baseURIDecl().uriLiteral());
URI uri = URILiteralUtils.resolve(
this.moduleContext.getStaticBaseURI(),
URI uri = URILiteralUtils.resolveStaticBaseUri(
this.moduleContext.getStaticBaseURIOrNull(),
uriString,
createMetadataFromContext(setterContext.baseURIDecl())
);
this.moduleContext.setStaticBaseUri(uri);
this.moduleContext.setStaticBaseUri(uri, URILiteralUtils.toStaticBaseUriString(uri, uriString));
flags.baseURISet = true;
return;
}
Expand Down Expand Up @@ -3746,16 +3741,16 @@ private void processDefaultCollation(DefaultCollationDeclContext ctx) {
private String resolveCollationUri(UriLiteralContext ctx) {
String uriString = processURILiteral(ctx);
URI uri = URILiteralUtils.resolve(
this.moduleContext.getStaticBaseURI(),
this.moduleContext.getStaticBaseURIOrNull(),
uriString,
createMetadataFromContext(ctx)
);
return uri.toString();
}

public LibraryModule processModuleImport(XQueryParser.ModuleImportContext ctx) {
String namespace = processURILiteral(ctx.targetNamespace);
ExceptionMetadata metadata = createMetadataFromContext(ctx);
String namespace = processURILiteral(ctx.targetNamespace);
if (namespace.isEmpty()) {
throw new EmptyModuleURIException("Module URI is empty.", metadata);
}
Expand All @@ -3768,8 +3763,10 @@ public LibraryModule processModuleImport(XQueryParser.ModuleImportContext ctx) {
);
}
}
namespace = URILiteralUtils.normalizeAsAnyURI(namespace);
List<String> locationHints = ctx.locations.stream()
.map(this::processURILiteral)
.map(URILiteralUtils::normalizeAsAnyURI)
.collect(Collectors.toList());
LibraryModule libraryModule = ModuleImportLoader.load(
namespace,
Expand All @@ -3789,7 +3786,8 @@ public LibraryModule processModuleImport(XQueryParser.ModuleImportContext ctx) {
}

public ExceptionMetadata generateMetadata(Token start, Token end) {
return ExceptionMetadata.fromTokens(this.moduleContext.getStaticBaseURI().toString(), start, end, this.code);
String location = this.moduleContext.getStaticBaseUriStringOrNull();
return ExceptionMetadata.fromTokens(location == null ? "unknown" : location, start, end, this.code);
}

private List<Annotation> processAnnotations(XQueryParser.AnnotationsContext annotations) {
Expand Down
40 changes: 38 additions & 2 deletions src/main/java/org/rumbledb/compiler/utils/URILiteralUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,58 @@
import org.rumbledb.runtime.functions.input.FileSystemUtil;

import java.net.URI;
import java.net.URISyntaxException;

public final class URILiteralUtils {

private static final String XML_WHITESPACE_SEQUENCE = "[\\t\\n\\r ]+";

private URILiteralUtils() {
}

public static String normalizeAsAnyURI(String literal) {
return literal.replaceAll(XML_WHITESPACE_SEQUENCE, " ").trim();
}

public static URI resolve(URI baseURI, String literal, ExceptionMetadata metadata) {
String normalizedLiteral = normalizeAsAnyURI(literal);
try {
return FileSystemUtil.resolveURI(baseURI, literal, metadata);
return FileSystemUtil.resolveURI(baseURI, normalizedLiteral, metadata);
} catch (CannotRetrieveResourceException exception) {
InvalidURILiteralException result = new InvalidURILiteralException(
"Invalid URI literal: " + literal,
"Invalid URI literal: " + normalizedLiteral,
metadata
);
result.initCause(exception);
throw result;
}
}

public static URI resolveStaticBaseUri(URI baseURI, String literal, ExceptionMetadata metadata) {
String normalizedLiteral = normalizeAsAnyURI(literal);
try {
URI parsedLiteral = FileSystemUtil.parseURIReference(normalizedLiteral);
if (!parsedLiteral.isAbsolute() && baseURI == null) {
return null;
}
return FileSystemUtil.resolveURI(baseURI, normalizedLiteral, metadata);
} catch (CannotRetrieveResourceException | URISyntaxException exception) {
InvalidURILiteralException result = new InvalidURILiteralException(
"Invalid URI literal: " + normalizedLiteral,
metadata
);
result.initCause(exception);
throw result;
}
}

public static String toStaticBaseUriString(URI resolvedURI, String literal) {
String normalizedLiteral = normalizeAsAnyURI(literal);
try {
URI parsedLiteral = new URI(normalizedLiteral);
return parsedLiteral.isAbsolute() ? normalizedLiteral : resolvedURI.toString();
} catch (URISyntaxException e) {
return normalizedLiteral;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class RuntimeStaticContext implements Serializable {
private static final long serialVersionUID = 1L;

private final URI staticURI;
private final String staticURIString;

/**
* Query language associated with this context, which is used for error reporting and to determine the
Expand Down Expand Up @@ -133,7 +134,8 @@ public static class RuntimeStaticContextBuilder {
*/
public static RuntimeStaticContextBuilder fromStaticContext(@NonNull StaticContext staticContext) {
return builder()
.staticURI(staticContext.getStaticBaseURI())
.staticURI(staticContext.getStaticBaseURIOrNull())
.staticURIString(staticContext.getStaticBaseUriStringOrNull())
.queryLanguage(staticContext.getQueryLanguage())
.staticallyKnownNamespaces(staticContext.getInScopeNamespaceBindings())
.staticallyKnownCollations(staticContext.getStaticallyKnownCollations())
Expand Down
39 changes: 39 additions & 0 deletions src/main/java/org/rumbledb/context/StaticContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public class StaticContext {
private String queryLanguage;
private StaticContext parent;
private URI staticBaseURI;
private String staticBaseUriString;
private boolean emptySequenceOrderLeast;
private boolean boundarySpacePreserve;
private boolean copyNamespacesPreserve;
Expand Down Expand Up @@ -96,6 +97,7 @@ public class StaticContext {
public StaticContext() {
this.parent = null;
this.staticBaseURI = null;
this.staticBaseUriString = null;
this.queryLanguage = null;
this.inScopeVariables = null;
this.userDefinedFunctionExecutionModes = null;
Expand All @@ -118,6 +120,7 @@ public StaticContext() {
public StaticContext(URI staticBaseURI, RumbleRuntimeConfiguration configuration) {
this.parent = null;
this.staticBaseURI = staticBaseURI;
this.staticBaseUriString = staticBaseURI == null ? null : staticBaseURI.toString();
this.queryLanguage = configuration.getQueryLanguage() != null
? configuration.getQueryLanguage()
: this.queryLanguage;
Expand Down Expand Up @@ -212,8 +215,44 @@ public URI getStaticBaseURI() {
throw new OurBadException("Static base URI not set.");
}

public URI getStaticBaseURIOrNull() {
if (this.staticBaseURI != null) {
return this.staticBaseURI;
}
if (this.parent != null) {
return this.parent.getStaticBaseURIOrNull();
}
return null;
}

public String getStaticBaseUriString() {
if (this.staticBaseUriString != null) {
return this.staticBaseUriString;
}
if (this.parent != null) {
return this.parent.getStaticBaseUriString();
}
throw new OurBadException("Static base URI not set.");
}

public String getStaticBaseUriStringOrNull() {
if (this.staticBaseUriString != null) {
return this.staticBaseUriString;
}
if (this.parent != null) {
return this.parent.getStaticBaseUriStringOrNull();
}
return null;
}

public void setStaticBaseUri(URI staticBaseURI) {
this.staticBaseURI = staticBaseURI;
this.staticBaseUriString = staticBaseURI == null ? null : staticBaseURI.toString();
}

public void setStaticBaseUri(URI staticBaseURI, String staticBaseUriString) {
this.staticBaseURI = staticBaseURI;
this.staticBaseUriString = staticBaseUriString;
}

public boolean isInScope(Name varName) {
Expand Down
Loading
Loading