From f86115e8f9ee76f275692805158164843c427a14 Mon Sep 17 00:00:00 2001 From: Peter Kajsa Date: Thu, 14 Jul 2016 10:45:41 +0200 Subject: [PATCH] Bug 6131 - NPE on malformed yang model Handling of NPE when source model does not contain any valid root element. Change-Id: I76d4aeb257cd2e20e75447fa2fc53e455063a8ae Signed-off-by: Peter Kajsa --- .../stmt/reactor/SourceSpecificContext.java | 35 ++++++++++--------- .../yangtools/yang/stmt/Bug6131Test.java | 28 +++++++++++++++ .../src/test/resources/bugs/bug6131/foo.yang | 2 ++ 3 files changed, 48 insertions(+), 17 deletions(-) create mode 100644 yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug6131Test.java create mode 100644 yang/yang-parser-impl/src/test/resources/bugs/bug6131/foo.yang diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java index c2d06d6035..297b99561a 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java @@ -124,7 +124,7 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh def = resolveTypeBodyStmts(name.getLocalName()); } } else if (current != null && current.definition().getRepresentingClass().equals(UnknownStatementImpl.class)) { - QName qName = Utils.qNameFromArgument(current, name.getLocalName()); + final QName qName = Utils.qNameFromArgument(current, name.getLocalName()); def = new StatementDefinitionContext<>(new UnknownStatementImpl.Definition( getNewStatementDefinition(qName))); @@ -176,7 +176,7 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh void startPhase(final ModelProcessingPhase phase) { @Nullable - ModelProcessingPhase previousPhase = phase.getPreviousPhase(); + final ModelProcessingPhase previousPhase = phase.getPreviousPhase(); Preconditions.checkState(Objects.equals(previousPhase, finishedPhase)); Preconditions.checkState(modifiers.get(previousPhase).isEmpty()); inProgressPhase = phase; @@ -202,8 +202,8 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh if (potentialLocal != null) { return potentialLocal; } - for (NamespaceStorageNode importedSource : importedNamespaces) { - V potential = importedSource.getFromLocalStorage(type, key); + for (final NamespaceStorageNode importedSource : importedNamespaces) { + final V potential = importedSource.getFromLocalStorage(type, key); if (potential != null) { return potential; } @@ -242,11 +242,12 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh } PhaseCompletionProgress tryToCompletePhase(final ModelProcessingPhase phase) throws SourceException { - Collection currentPhaseModifiers = modifiers.get(phase); + final Collection currentPhaseModifiers = modifiers.get(phase); boolean hasProgressed = tryToProgress(currentPhaseModifiers); - boolean phaseCompleted = root.tryToCompletePhase(phase); + Preconditions.checkNotNull(this.root, "Malformed source. Valid root element is missing."); + final boolean phaseCompleted = root.tryToCompletePhase(phase); hasProgressed = (tryToProgress(currentPhaseModifiers) | hasProgressed); @@ -278,7 +279,7 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh } ModelActionBuilder newInferenceAction(final ModelProcessingPhase phase) { - ModifierImpl action = new ModifierImpl(phase); + final ModifierImpl action = new ModifierImpl(phase); modifiers.put(phase, action); return action; } @@ -291,10 +292,10 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh SourceException failModifiers(final ModelProcessingPhase identifier) { final List exceptions = new ArrayList<>(); - for (ModifierImpl mod : modifiers.get(identifier)) { + for (final ModifierImpl mod : modifiers.get(identifier)) { try { mod.failModifier(); - } catch (SourceException e) { + } catch (final SourceException e) { exceptions.add(e); } } @@ -355,13 +356,13 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh } private PrefixToModule preLinkagePrefixes() { - PrefixToModuleMap preLinkagePrefixes = new PrefixToModuleMap(true); - Map prefixToNamespaceMap = getAllFromLocalStorage(ImpPrefixToNamespace.class); + final PrefixToModuleMap preLinkagePrefixes = new PrefixToModuleMap(true); + final Map prefixToNamespaceMap = getAllFromLocalStorage(ImpPrefixToNamespace.class); if (prefixToNamespaceMap == null) { //:FIXME if it is a submodule without any import, the map is null. Handle also submodules and includes... return null; } - for (Entry prefixToNamespace : prefixToNamespaceMap.entrySet()) { + for (final Entry prefixToNamespace : prefixToNamespaceMap.entrySet()) { preLinkagePrefixes.put(prefixToNamespace.getKey(), QNameModule.create(prefixToNamespace.getValue(), null)); } @@ -377,7 +378,7 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh allPrefixes.putAll(belongsToPrefixes); } - for (Entry stringModuleIdentifierEntry : allPrefixes.entrySet()) { + for (final Entry stringModuleIdentifierEntry : allPrefixes.entrySet()) { final QNameModule namespace = getRoot().getFromNamespace(ModuleIdentifierToModuleQName.class, stringModuleIdentifierEntry.getValue()); prefixToModuleMap.put(stringModuleIdentifierEntry.getKey(), namespace); @@ -387,18 +388,18 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh private QNameToStatementDefinition stmtDef() { // regular YANG statements and extension supports added - ImmutableMap> definitions = currentContext.getSupportsForPhase( + final ImmutableMap> definitions = currentContext.getSupportsForPhase( inProgressPhase).getDefinitions(); - for (Entry> entry : definitions.entrySet()) { + for (final Entry> entry : definitions.entrySet()) { qNameToStmtDefMap.put(entry.getKey(), entry.getValue()); } // extensions added if (inProgressPhase.equals(ModelProcessingPhase.FULL_DECLARATION)) { - Map>> extensions = + final Map>> extensions = currentContext.getAllFromNamespace(ExtensionNamespace.class); if (extensions != null) { - for (Entry>> extension : + for (final Entry>> extension : extensions.entrySet()) { if(qNameToStmtDefMap.get(extension.getKey()) == null) { qNameToStmtDefMap.put((extension.getKey()), diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug6131Test.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug6131Test.java new file mode 100644 index 0000000000..e8d1f752a0 --- /dev/null +++ b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug6131Test.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.yangtools.yang.stmt; + +import static org.junit.Assert.assertEquals; + +import java.io.FileNotFoundException; +import java.net.URISyntaxException; +import org.junit.Test; +import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException; +import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; + +public class Bug6131Test { + @Test + public void test() throws ReactorException, SourceException, FileNotFoundException, URISyntaxException { + try { + StmtTestUtils.parseYangSources("/bugs/bug6131"); + } catch (final Exception e) { + assertEquals("Malformed source. Valid root element is missing.", e.getMessage()); + } + } +} \ No newline at end of file diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug6131/foo.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug6131/foo.yang new file mode 100644 index 0000000000..acf884530f --- /dev/null +++ b/yang/yang-parser-impl/src/test/resources/bugs/bug6131/foo.yang @@ -0,0 +1,2 @@ +container foo { +} \ No newline at end of file -- 2.36.6