From: Robert Varga Date: Mon, 9 Nov 2015 08:27:39 +0000 (+0100) Subject: BUG-4599: do not attempt to construct invalid QNames X-Git-Tag: release/carbon~211 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=7afe82dabbbc39b0ecf52772f5b9a4eaf4c8dacd;p=yangtools.git BUG-4599: do not attempt to construct invalid QNames QName should not allow for localname to contain ':', so do not construct it just for lookups. Also move the code to its only user, so we can evolve it. Change-Id: Ib6c2b9aa0ea3fa14c1d843162a4b232a12e10cc4 Signed-off-by: Robert Varga --- diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangStatementParserListenerImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangStatementParserListenerImpl.java index 45bde58754..c20c2d1e17 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangStatementParserListenerImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangStatementParserListenerImpl.java @@ -18,7 +18,9 @@ import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.KeywordCo import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.StatementContext; import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParserBaseListener; import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.QNameModule; import org.opendaylight.yangtools.yang.common.YangConstants; +import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition; import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase; import org.opendaylight.yangtools.yang.parser.spi.source.DeclarationInTextSource; import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule; @@ -73,8 +75,7 @@ public class YangStatementParserListenerImpl extends YangStatementParserBaseList final StatementSourceReference ref = DeclarationInTextSource.atPosition(sourceName, ctx .getStart().getLine(), ctx.getStart().getCharPositionInLine()); final String keywordTxt = Verify.verifyNotNull(ctx.getChild(KeywordContext.class, 0)).getText(); - final QName identifier = QName.create(YangConstants.RFC6020_YIN_MODULE, keywordTxt); - final QName validStatementDefinition = Utils.getValidStatementDefinition(prefixes, stmtDef, identifier); + final QName validStatementDefinition = getValidStatementDefinition(prefixes, stmtDef, keywordTxt); final int childId = counters.peek().getAndIncrement(); counters.push(new Counter()); @@ -97,8 +98,7 @@ public class YangStatementParserListenerImpl extends YangStatementParserBaseList KeywordContext keyword = ctx.getChild(KeywordContext.class, 0); String statementName = keyword.getText(); - QName identifier = QName.create(YangConstants.RFC6020_YIN_MODULE, statementName); - if (stmtDef != null && Utils.getValidStatementDefinition(prefixes, stmtDef, identifier) != null + if (stmtDef != null && getValidStatementDefinition(prefixes, stmtDef, statementName) != null && toBeSkipped.isEmpty()) { writer.endStatement(ref); } @@ -107,4 +107,51 @@ public class YangStatementParserListenerImpl extends YangStatementParserBaseList toBeSkipped.remove(statementName); counters.pop(); } + + /** + * Based on identifier read from source and collections of relevant prefixes and statement definitions mappings + * provided for actual phase, method resolves and returns valid QName for declared statement to be written. + * This applies to any declared statement, including unknown statements. + * + * @param prefixes collection of all relevant prefix mappings supplied for actual parsing phase + * @param stmtDef collection of all relevant statement definition mappings provided for actual parsing phase + * @param keywordText statement keyword text to parse from source + * @return valid QName for declared statement to be written, or null + */ + private static QName getValidStatementDefinition(final PrefixToModule prefixes, + final QNameToStatementDefinition stmtDef, final String keywordText) { + final int firstColon = keywordText.indexOf(':'); + if (firstColon == -1) { + final StatementDefinition statementDefinition = stmtDef.get( + new QName(YangConstants.RFC6020_YIN_NAMESPACE, keywordText)); + return statementDefinition != null ? statementDefinition.getStatementName() : null; + } + + final int secondColon = keywordText.indexOf(':', firstColon + 1); + if (secondColon != -1) { + // Malformed string + return null; + } + if (prefixes == null) { + // No prefixes to look up from + return null; + } + + final String prefix = keywordText.substring(0, firstColon); + final QNameModule qNameModule = prefixes.get(prefix); + if (qNameModule == null) { + // Failed to look the namespace + return null; + } + + final String localName = keywordText.substring(firstColon + 1); + final StatementDefinition foundStmtDef; + if (prefixes.isPreLinkageMap()) { + foundStmtDef = stmtDef.getByNamespaceAndLocalName(qNameModule.getNamespace(), localName); + } else { + foundStmtDef = stmtDef.get(QName.create(qNameModule, localName)); + } + + return foundStmtDef != null ? foundStmtDef.getStatementName() : null; + } } diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/Utils.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/Utils.java index 0a5bfbc8c0..86ffd0ae09 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/Utils.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/Utils.java @@ -41,7 +41,6 @@ import org.opendaylight.yangtools.yang.model.api.DeviateKind; import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier; import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath; import org.opendaylight.yangtools.yang.model.api.Status; -import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition; import org.opendaylight.yangtools.yang.model.api.stmt.BelongsToStatement; import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement; import org.opendaylight.yangtools.yang.model.api.stmt.RevisionStatement; @@ -61,8 +60,6 @@ import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToModuleIdenti import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleQName; import org.opendaylight.yangtools.yang.parser.spi.source.ModuleIdentifierToModuleQName; import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNameToModuleQName; -import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule; -import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition; import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; import org.opendaylight.yangtools.yang.parser.stmt.reactor.RootStatementContext; import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase; @@ -394,51 +391,6 @@ public final class Utils { return identifier; } - /** - * - * Based on identifier read from source and collections of relevant prefixes and statement definitions mappings - * provided for actual phase, method resolves and returns valid QName for declared statement to be written. - * This applies to any declared statement, including unknown statements. - * - * @param prefixes - collection of all relevant prefix mappings supplied for actual parsing phase - * @param stmtDef - collection of all relevant statement definition mappings provided for actual parsing phase - * @param identifier - statement to parse from source - * @return valid QName for declared statement to be written - * - */ - public static QName getValidStatementDefinition(final PrefixToModule prefixes, - final QNameToStatementDefinition stmtDef, final QName identifier) { - final StatementDefinition def = stmtDef.get(identifier); - if (def != null) { - return def.getStatementName(); - } - if (prefixes == null) { - return null; - } - - final String prefixedLocalName = identifier.getLocalName(); - final String[] namesParts = prefixedLocalName.split(":"); - if (namesParts.length != 2) { - return null; - } - - final String prefix = namesParts[0]; - final String localName = namesParts[1]; - final QNameModule qNameModule = prefixes.get(prefix); - if (qNameModule == null) { - return null; - } - - if (prefixes.isPreLinkageMap()) { - final StatementDefinition foundStmtDef = stmtDef.getByNamespaceAndLocalName(qNameModule.getNamespace(), - localName); - return foundStmtDef != null ? foundStmtDef.getStatementName() : null; - } - - final QName qName = QName.create(qNameModule, localName); - return stmtDef.get(qName) != null ? qName : null; - } - static SchemaNodeIdentifier nodeIdentifierFromPath(final StmtContext ctx, final String path) { // FIXME: is the path trimming really necessary?? final List qNames = new ArrayList<>();