package org.graalvm.component.installer.persist;
import java.util.Collections;
import org.graalvm.component.installer.MetadataException;
import org.graalvm.component.installer.DependencyException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import org.graalvm.component.installer.BundleConstants;
import org.graalvm.component.installer.Feedback;
import org.graalvm.component.installer.Version;
import org.graalvm.component.installer.model.StabilityLevel;
public class {
private static final String = "filter";
private final String ;
private final Map<String, String> = new HashMap<>();
private final Map<String, String> = new HashMap<>();
private final Map<String, String> = new HashMap<>();
private final Map<String, Object> = new HashMap<>();
private final Set<String> = new HashSet<>();
private final Feedback ;
private String ;
private int ;
private String ;
private int ;
private String ;
public (String headerName, String header, Feedback feedback) {
this.headerName = headerName;
this.feedback = feedback.withBundle(HeaderParser.class);
if (header != null) {
this.header = header.trim();
} else {
this.header = "";
}
}
private MetadataException (String key, Object... args) {
return new MetadataException(headerName, feedback.l10n(key, args));
}
public HeaderParser () throws MetadataException {
if (header == null || header.isEmpty()) {
throw metaEx("ERROR_HeaderMissing", headerName);
}
return this;
}
private static boolean (char c) {
return (c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z');
}
private static boolean (char c) {
return isAlphaNum(c) || c == '_' || c == '-';
}
private static boolean (char c) {
return isToken(c) || c == '.';
}
public boolean (Boolean defValue) {
if (pos >= header.length()) {
if (defValue == null) {
throw metaEx("ERROR_HeaderMissing", headerName);
}
return defValue;
} else {
String s = header.substring(pos).trim().toLowerCase(Locale.ENGLISH);
switch (s) {
case "true":
return true;
case "false":
return false;
}
throw metaEx("ERROR_HeaderInvalid", headerName, s);
}
}
public String (String defValue) {
if (pos >= header.length()) {
return defValue;
} else {
return header.substring(pos).trim();
}
}
private void (String attrName, String value) {
if (filterValue.put(attrName, value) != null) {
throw metaErr("ERROR_DuplicateFilterAttribute");
}
}
private boolean () {
return pos >= header.length();
}
public String () throws MetadataException {
return parseNameOrNamespace(HeaderParser::isToken, "ERROR_MissingSymbolicName", "ERROR_InvalidSymbolicName", '.');
}
private char () {
return pos < header.length() ? header.charAt(pos++) : 0;
}
private void () {
pos++;
}
private char () {
return isEmpty() ? 0 : header.charAt(pos);
}
private String () {
String s = cut();
skipWhitespaces();
return s;
}
private void () {
while (!isEmpty()) {
if (!Character.isWhitespace(ch())) {
contentStart = pos;
return;
}
advance();
}
contentStart = -1;
}
private void () {
skipWhitespaces();
if (ch() == ';') {
advance();
}
contentStart = -1;
}
private String () {
return cut(0);
}
private String (int delim) {
int e = pos - delim;
return contentStart == -1 || contentStart >= e ? "" : header.substring(contentStart, e);
}
private void () {
contentStart = pos;
}
private String () throws MetadataException {
skipWhitespaces();
while (!isEmpty()) {
char c = next();
if (Character.isWhitespace(c)) {
break;
}
if (c == ';') {
pos--;
break;
}
if (!isExtended(c)) {
throw metaEx("ERROR_InvalidParameterSyntax", directiveOrParameterName);
}
}
String s = cut();
skipWithSemicolon();
return s;
}
private String () throws MetadataException {
markContent();
while (!isEmpty()) {
char c = next();
switch (c) {
case '"':
String s = cut(1);
skipWithSemicolon();
return s;
case '\n':
case '\r':
case 0:
throw metaEx("ERROR_InvalidQuotedString");
case '\\':
next();
break;
}
}
throw metaEx("ERROR_InvalidQuotedString");
}
private String () throws MetadataException {
skipWhitespaces();
char c = ch();
if (c == ';') {
throw metaEx("ERROR_MissingArgument", directiveOrParameterName);
}
if (c == '"') {
advance();
return readQuotedParameter();
} else {
return readExtendedParameter();
}
}
private String (Predicate<Character> charAcceptor,
String missingKeyName, String invalidKeyName, char compDelimiter) throws MetadataException {
if (header == null || isEmpty()) {
throw metaEx(missingKeyName);
}
skipWhitespaces();
boolean componentEmpty = true;
while (!isEmpty()) {
char c = ch();
if (c == ';' || c == ',') {
String s = cut();
return s;
}
advance();
if (c == compDelimiter) {
if (componentEmpty) {
throw metaEx(invalidKeyName);
}
componentEmpty = true;
continue;
}
if (Character.isWhitespace(c)) {
break;
}
if (!charAcceptor.test(c)) {
throw metaEx(invalidKeyName);
}
componentEmpty = false;
}
return returnCut();
}
private String () throws MetadataException {
return parseNameOrNamespace(HeaderParser::isExtended, "ERROR_MissingCapabilityName", "ERROR_InvalidCapabilityName", (char) 0);
}
public String () throws MetadataException {
int versionStart = -1;
int partCount = 0;
boolean partContents = false;
if (isEmpty()) {
throw metaErr("ERROR_InvalidVersion");
}
boolean dash = false;
while (!isEmpty()) {
char c = ch();
if (Character.isWhitespace(c)) {
if (versionStart != -1) {
break;
}
advance();
continue;
}
if (c == ';') {
break;
}
advance();
if (c == '.') {
++partCount;
if (!partContents) {
throw metaErr("ERROR_InvalidVersion");
}
partContents = false;
dash = false;
continue;
}
if (partCount > 0 && partContents && c == '-') {
dash = true;
continue;
}
if (c >= '0' && c <= '9') {
if (versionStart == -1) {
versionStart = pos - 1;
}
} else {
if (partCount < 1) {
throw metaErr("ERROR_InvalidVersion");
}
boolean err = false;
if (partCount >= 3 || dash) {
err = !isToken(c);
} else {
err = true;
}
if (err) {
throw metaErr("ERROR_InvalidVersion");
}
}
partContents = true;
}
String v = cut();
skipWhitespaces();
if (!isEmpty() || !partContents) {
throw metaErr("ERROR_InvalidVersion");
}
return v;
}
private String () {
skipWhitespaces();
while (!isEmpty()) {
char c = ch();
if (isExtended(c)) {
advance();
} else if (Character.isWhitespace(c) || c == ':' || c == '=' || c == ';') {
break;
} else {
throw metaEx("ERROR_InvalidParameterName");
}
}
return returnCut();
}
private void () {
while (!isEmpty()) {
String paramOrDirectiveName = readExtendedName();
if (paramOrDirectiveName.isEmpty()) {
throw metaEx("ERROR_InvalidParameterName");
}
directiveOrParameterName = paramOrDirectiveName;
char c = ch();
boolean dcolon = c == ':';
if (dcolon) {
advance();
}
c = next();
if (c != '=') {
throw metaEx("ERROR_InvalidParameterSyntax", paramOrDirectiveName);
}
(dcolon ? directives : parameters).put(paramOrDirectiveName, parseArgument());
}
}
private void (String text) {
this.header = text;
this.pos = 0;
}
private MetadataException (String key, Object... args) throws MetadataException {
throw metaEx(key, args);
}
private MetadataException () throws MetadataException {
throw metaErr("ERROR_InvalidFilterSpecification");
}
private void () {
skipWhitespaces();
char c = next();
while (c == '(') {
parseFilterContent();
c = next();
}
if (c != ')') {
throw filterError();
}
}
private void () {
skipWhitespaces();
int lastPos = -1;
W: while (!isEmpty()) {
char c = ch();
if (Character.isWhitespace(c)) {
if (lastPos == -1) {
lastPos = pos;
}
continue;
}
switch (c) {
case '=':
case '<':
case '>':
case '~':
case '(':
case ')':
break W;
}
lastPos = -1;
advance();
}
String attributeName = returnCut();
char c = next();
if (c != '=') {
throw metaErr("ERROR_UnsupportedFilterOperation");
}
c = ch();
if (c == '*') {
throw metaErr("ERROR_UnsupportedFilterOperation");
}
markContent();
while (!isEmpty()) {
c = next();
if (c == ')') {
addFilterAttribute(attributeName, cut(1));
skipWhitespaces();
return;
}
switch (c) {
case '\\':
c = next();
if (c == 0) {
throw filterError();
}
break;
case '*':
throw metaErr("ERROR_UnsupportedFilterOperation");
case '(':
case '<':
case '>':
case '~':
case '=':
throw filterError();
}
}
throw filterError();
}
private void () {
skipWhitespaces();
char o = ch();
if (o == '&') {
advance();
parseFilterConjunction();
} else if (isExtended(o)) {
parseFilterClause();
} else {
throw metaErr("ERROR_InvalidFilterSpecification");
}
}
private void () {
skipWhitespaces();
if (isEmpty()) {
throw filterError();
}
char c = next();
if (c == '(') {
parseFilterContent();
skipWhitespaces();
if (!isEmpty()) {
throw metaErr("ERROR_InvalidFilterSpecification");
}
} else {
throw filterError();
}
}
public Map<String, String> () {
String namespace = parseNamespace();
char c = next();
if (c != ';' && c != 0) {
throw metaErr("ERROR_InvalidFilterSpecification");
}
if (!BundleConstants.GRAALVM_CAPABILITY.equals(namespace)) {
throw new MetadataException(BundleConstants.BUNDLE_REQUIRED, feedback.l10n("ERROR_UnknownCapability"));
}
parseParameters();
if (!parameters.isEmpty()) {
throw metaErr("ERROR_UnsupportedParameters");
}
versionFilter = directives.remove(DIRECTIVE_FILTER);
if (!directives.isEmpty()) {
throw metaErr("ERROR_UnsupportedDirectives");
}
if (versionFilter == null) {
throw metaErr("ERROR_MissingVersionFilter");
}
replaceInputText(versionFilter);
parseFilterSpecification();
return filterValue;
}
public Map<String, Object> () {
if (isEmpty()) {
return Collections.emptyMap();
}
String namespace = parseNamespace();
char c = next();
if (c != ';' && c != 0) {
throw metaErr("ERROR_InvalidCapabilitySyntax");
}
if (!BundleConstants.GRAALVM_CAPABILITY.equals(namespace)) {
throw new DependencyException(namespace, null, null, feedback.l10n("ERROR_UnknownCapability"));
}
while (!isEmpty()) {
parseCapability();
}
return capabilities;
}
public StabilityLevel () {
if (isEmpty()) {
return StabilityLevel.Undefined;
}
return StabilityLevel.valueOfMixedCase(getContents(""));
}
public Set<String> () {
if (isEmpty()) {
return Collections.emptySet();
}
while (!isEmpty()) {
String sn = parseSymbolicName();
dependencies.add(sn);
skipWhitespaces();
if (isEmpty()) {
break;
}
char c = next();
switch (c) {
case ',':
break;
case ';':
throw metaEx("ERROR_DependencyParametersNotSupported");
}
}
return dependencies;
}
private void () {
String capName = readExtendedName();
if (capName.isEmpty()) {
throw metaEx("ERROR_InvalidCapabilityName");
}
directiveOrParameterName = capName;
char c = next();
boolean dcolon = c == ':';
boolean makeVersion = false;
if (dcolon) {
if (ch() == '=') {
throw metaEx("ERROR_InvalidCapabilitySyntax", capName);
}
skipWhitespaces();
while (true) {
if (isEmpty()) {
throw metaEx("ERROR_InvalidCapabilitySyntax", capName);
}
c = next();
if (Character.isWhitespace(c) || c == '=' || c == ';') {
if (isEmpty()) {
throw metaEx("ERROR_InvalidCapabilitySyntax", capName);
}
break;
} else if (!isAlphaNum(c)) {
throw metaEx("ERROR_InvalidCapabilitySyntax", capName);
}
}
String type = cut(1);
switch (type.toLowerCase(Locale.ENGLISH)) {
case "version":
makeVersion = true;
break;
case "string":
break;
case "long":
case "double":
case "":
default:
throw metaEx("ERROR_UnsupportedCapabilityType", capName, type);
}
skipWhitespaces();
}
if (c != '=') {
throw metaEx("ERROR_InvalidCapabilitySyntax", capName);
}
String s = parseArgument();
Object o;
if (makeVersion) {
try {
o = Version.fromString(s);
} catch (IllegalArgumentException ex) {
throw metaEx("ERROR_InvalidCapabilityVersion", capName, s);
}
} else {
o = s;
}
capabilities.put(capName, o);
}
}