From 80b2a1b0f1fd86816047487fc97e1da5f3188ea4 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Mon, 30 Nov 2020 17:30:24 +0100 Subject: [PATCH] Do not use exceptions for branching UnrecognizedEffectiveStatementImpl is mis-using StmtContextUtils.qnameFromArgument() to attempt to create a QName, suppressing reported exceptions. Use a custom-tailored lookup, which utilizes AbstractQName.isValidLocalName() and thus side-steps exceptions. JIRA: YANGTOOLS-1191 Change-Id: Iecea9f446730e4e7840b962a95844ce5128dfb9e Signed-off-by: Robert Varga (cherry picked from commit 1bbcdd2d6510d420b916c26f54c60a1c2e1607df) --- .../yangtools/yang/common/AbstractQName.java | 17 +++++++- .../UnrecognizedEffectiveStatementImpl.java | 40 ++++++++++++++----- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/AbstractQName.java b/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/AbstractQName.java index d45cdbed5b..d24ed22b1c 100644 --- a/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/AbstractQName.java +++ b/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/AbstractQName.java @@ -72,12 +72,25 @@ public abstract class AbstractQName implements Identifier, WritableObject { return new QName(namespace, getLocalName()); } + /** + * Check whether a string is a valid {@code localName}. + * + * @param str String to check + * @return True if the string usable as a local name, false otherwise + */ + public static final boolean isValidLocalName(final @Nullable String str) { + return str != null && !str.isEmpty() && checkContent(str); + } + abstract Object writeReplace(); static final String checkLocalName(final @Nullable String localName) { checkArgument(!localName.isEmpty(), "Parameter 'localName' must be a non-empty string."); - checkArgument(IDENTIFIER_START.matches(localName.charAt(0)) && NOT_IDENTIFIER_PART.indexIn(localName, 1) == -1, - "String '%s' is not a valid identifier", localName); + checkArgument(checkContent(localName), "String '%s' is not a valid identifier", localName); return localName; } + + private static boolean checkContent(final String localName) { + return IDENTIFIER_START.matches(localName.charAt(0)) && NOT_IDENTIFIER_PART.indexIn(localName, 1) == -1; + } } diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/extension/UnrecognizedEffectiveStatementImpl.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/extension/UnrecognizedEffectiveStatementImpl.java index b186450f6f..1f02d8b98a 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/extension/UnrecognizedEffectiveStatementImpl.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/extension/UnrecognizedEffectiveStatementImpl.java @@ -9,7 +9,9 @@ package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.extension; import com.google.common.collect.ImmutableList; import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.yangtools.yang.common.AbstractQName; import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.QNameModule; import org.opendaylight.yangtools.yang.model.api.SchemaPath; import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; @@ -38,17 +40,11 @@ final class UnrecognizedEffectiveStatementImpl extends UnknownEffectiveStatement // FIXME: Remove following section after fixing 4380 final UnknownSchemaNode original = (UnknownSchemaNode) ctx.getOriginalCtx().map(StmtContext::buildEffective) .orElse(null); - if (original != null) { - this.maybeQNameArgument = original.getQName(); + if (original == null) { + final QName qname = qnameFromArgument(ctx); + maybeQNameArgument = qname != null ? qname : getNodeType(); } else { - QName maybeQNameArgumentInit = null; - try { - maybeQNameArgumentInit = StmtContextUtils.qnameFromArgument(ctx, argument()); - } catch (SourceException e) { - LOG.debug("Not constructing QName from {}", argument(), e); - maybeQNameArgumentInit = getNodeType(); - } - this.maybeQNameArgument = maybeQNameArgumentInit; + maybeQNameArgument = original.getQName(); } SchemaPath maybePath; @@ -77,4 +73,28 @@ final class UnrecognizedEffectiveStatementImpl extends UnknownEffectiveStatement public StatementDefinition statementDefinition() { return getDeclared().statementDefinition(); } + + private static QName qnameFromArgument(final StmtContext stmt) { + final String value = stmt.getStatementArgument(); + if (value == null || value.isEmpty()) { + return stmt.getPublicDefinition().getStatementName(); + } + + final int colon = value.indexOf(':'); + if (colon == -1) { + if (AbstractQName.isValidLocalName(value)) { + return QName.unsafeOf(StmtContextUtils.getRootModuleQName(stmt), value).intern(); + } + return null; + } + + final QNameModule qnameModule = StmtContextUtils.getModuleQNameByPrefix(stmt, value.substring(0, colon)); + if (qnameModule == null) { + return null; + } + + final int next = value.indexOf(':', colon + 1); + final String localName = next == -1 ? value.substring(colon + 1) : value.substring(colon + 1, next); + return QName.create(qnameModule, localName).intern(); + } } -- 2.36.6