From 6dae254dbc2940d1f0f372d65d69b0e0dda415fe Mon Sep 17 00:00:00 2001 From: Martin Bobak Date: Mon, 3 Mar 2014 11:17:50 +0100 Subject: [PATCH] Bug 451 - Fix netconf exception handling Change-Id: I815b34da996cf2660650577edb2e8ca623ae96df Signed-off-by: Martin Bobak --- .../test/impl/DepTestImplModuleFactory.java | 20 +++ .../test/impl/IdentityTestModuleFactory.java | 20 +++ .../impl/NetconfTestImplModuleFactory.java | 20 +++ .../yang/test/impl/TestImplModuleFactory.java | 20 +++ .../netconf/NetconfDeviceListener.java | 3 +- .../sal/connect/netconf/NetconfMapping.java | 19 +- .../netconf/config-netconf-connector/pom.xml | 6 +- .../NetconfConfigHandlingException.java | 26 +++ .../NoTransactionFoundException.java | 27 +++ .../OperationNotPermittedException.java | 26 +++ .../AbstractAttributeReadingStrategy.java | 9 +- .../ArrayAttributeReadingStrategy.java | 3 +- .../fromxml/AttributeReadingStrategy.java | 3 +- .../CompositeAttributeReadingStrategy.java | 6 +- .../ObjectNameAttributeReadingStrategy.java | 13 +- .../SimpleAttributeReadingStrategy.java | 15 +- ...leIdentityRefAttributeReadingStrategy.java | 3 +- .../mapping/config/Config.java | 23 +-- .../mapping/config/InstanceConfig.java | 22 ++- .../config/InstanceConfigElementResolved.java | 31 ++-- .../mapping/config/ModuleConfig.java | 3 +- .../config/ModuleElementDefinition.java | 20 ++- .../mapping/config/Services.java | 3 +- .../mapping/rpc/InstanceRuntimeRpc.java | 3 +- .../operations/Commit.java | 25 +-- .../operations/DiscardChanges.java | 26 +-- .../operations/Validate.java | 35 +--- .../AbstractEditConfigStrategy.java | 7 +- .../editconfig/DeleteEditConfigStrategy.java | 17 +- .../operations/editconfig/EditConfig.java | 93 ++++------ .../editconfig/EditConfigStrategy.java | 3 +- .../editconfig/EditConfigXmlParser.java | 40 ++++- .../editconfig/EditStrategyType.java | 17 ++ .../editconfig/MergeEditConfigStrategy.java | 30 +++- .../MissingInstanceHandlingStrategy.java | 9 +- .../editconfig/ReplaceEditConfigStrategy.java | 21 ++- .../operations/get/Get.java | 39 ++-- .../operations/getconfig/GetConfig.java | 41 +---- .../operations/runtimerpc/RuntimeRpc.java | 41 +++-- .../transactions/TransactionProvider.java | 11 +- .../NetconfMappingTest.java | 80 ++++----- .../operations/editconfig/EditConfigTest.java | 4 +- .../netconf/persist/impl/ConfigPusher.java | 14 +- .../impl/osgi/ConfigPersisterActivator.java | 8 +- .../api/NetconfDocumentedException.java | 6 + .../NetconfClientSessionNegotiator.java | 24 +-- ...NetconfClientSessionNegotiatorFactory.java | 26 ++- opendaylight/netconf/netconf-impl/pom.xml | 1 + ...NetconfServerSessionNegotiatorFactory.java | 30 ++-- .../mapping/operations/DefaultCommit.java | 34 ++-- .../mapping/operations/DefaultGetSchema.java | 37 ++-- .../impl/osgi/NetconfOperationRouterImpl.java | 19 +- .../controller/netconf/it/NetconfITTest.java | 11 +- .../netconf/mapping/api/NetconfOperation.java | 2 +- .../netconf/netconf-monitoring/pom.xml | 1 + .../controller/netconf/monitoring/Get.java | 14 +- .../netconf/ssh/NetconfSSHServer.java | 13 +- opendaylight/netconf/netconf-util/pom.xml | 3 +- .../AbstractNetconfSessionNegotiator.java | 9 +- .../controller/netconf/util/NetconfUtil.java | 7 +- .../exception/MissingNameSpaceException.java | 26 +++ .../exception/UnexpectedElementException.java | 26 +++ .../UnexpectedNamespaceException.java | 26 +++ .../mapping/AbstractLastNetconfOperation.java | 10 +- .../mapping/AbstractNetconfOperation.java | 15 +- .../util/messages/NetconfHelloMessage.java | 28 ++- .../util/messages/NetconfMessageUtil.java | 26 ++- .../netconf/util/xml/XmlElement.java | 169 +++++++++++++----- .../netconf/util/xml/XmlNetconfConstants.java | 2 + .../netconf/util/NetconfUtilTest.java | 3 +- 70 files changed, 925 insertions(+), 548 deletions(-) create mode 100644 opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModuleFactory.java create mode 100644 opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModuleFactory.java create mode 100644 opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleFactory.java create mode 100644 opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModuleFactory.java create mode 100644 opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/exception/NetconfConfigHandlingException.java create mode 100644 opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/exception/NoTransactionFoundException.java create mode 100644 opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/exception/OperationNotPermittedException.java create mode 100644 opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/MissingNameSpaceException.java create mode 100644 opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/UnexpectedElementException.java create mode 100644 opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/UnexpectedNamespaceException.java diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModuleFactory.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModuleFactory.java new file mode 100644 index 0000000000..330f804e0e --- /dev/null +++ b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModuleFactory.java @@ -0,0 +1,20 @@ +/* +* Copyright (c) 2013 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 +*/ +/* +* Generated file +* +* Generated from: yang module name: config-test-impl yang module local name: impl-dep +* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator +* Generated at: Fri Apr 25 09:12:08 CEST 2014 +* +* Do not modify this file unless it is present under src/main directory +*/ +package org.opendaylight.controller.config.yang.test.impl; +public class DepTestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractDepTestImplModuleFactory { + +} diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModuleFactory.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModuleFactory.java new file mode 100644 index 0000000000..b57d1dc1d4 --- /dev/null +++ b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModuleFactory.java @@ -0,0 +1,20 @@ +/* +* Copyright (c) 2013 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 +*/ +/* +* Generated file +* +* Generated from: yang module name: config-test-impl yang module local name: impl-identity-test +* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator +* Generated at: Fri Apr 25 09:12:08 CEST 2014 +* +* Do not modify this file unless it is present under src/main directory +*/ +package org.opendaylight.controller.config.yang.test.impl; +public class IdentityTestModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractIdentityTestModuleFactory { + +} diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleFactory.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleFactory.java new file mode 100644 index 0000000000..74a05496df --- /dev/null +++ b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleFactory.java @@ -0,0 +1,20 @@ +/* +* Copyright (c) 2013 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 +*/ +/* +* Generated file +* +* Generated from: yang module name: config-test-impl yang module local name: impl-netconf +* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator +* Generated at: Fri Apr 25 09:12:08 CEST 2014 +* +* Do not modify this file unless it is present under src/main directory +*/ +package org.opendaylight.controller.config.yang.test.impl; +public class NetconfTestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractNetconfTestImplModuleFactory { + +} diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModuleFactory.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModuleFactory.java new file mode 100644 index 0000000000..9680bffd6b --- /dev/null +++ b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModuleFactory.java @@ -0,0 +1,20 @@ +/* +* Copyright (c) 2013 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 +*/ +/* +* Generated file +* +* Generated from: yang module name: config-test-impl yang module local name: impl +* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator +* Generated at: Fri Apr 25 09:12:08 CEST 2014 +* +* Do not modify this file unless it is present under src/main directory +*/ +package org.opendaylight.controller.config.yang.test.impl; +public class TestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractTestImplModuleFactory { + +} diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceListener.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceListener.java index d6bf868b75..94f5e166a1 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceListener.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceListener.java @@ -18,6 +18,7 @@ import java.util.Iterator; import java.util.Queue; import java.util.Set; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.api.NetconfTerminationReason; import org.opendaylight.controller.netconf.client.NetconfClientSession; @@ -156,7 +157,7 @@ class NetconfDeviceListener implements NetconfClientSessionListener { try { NetconfMapping.checkSuccessReply(message); - } catch (IllegalStateException e) { + } catch (NetconfDocumentedException | IllegalStateException e) { LOG.warn("Error reply from remote device", e); r.future.setException(e); return; diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java index 3e729149eb..a6e6b3dfdf 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java @@ -7,6 +7,12 @@ */ package org.opendaylight.controller.sal.connect.netconf; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; import java.net.URI; import java.util.ArrayList; import java.util.Collections; @@ -14,10 +20,9 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; - import javax.activation.UnsupportedDataTypeException; import javax.annotation.Nullable; - +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil; import org.opendaylight.controller.netconf.util.xml.XmlUtil; @@ -41,14 +46,6 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.w3c.dom.Document; import org.w3c.dom.Element; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.base.Predicate; -import com.google.common.collect.Collections2; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; - public class NetconfMapping { public static URI NETCONF_URI = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0"); @@ -262,7 +259,7 @@ public class NetconfMapping { } } - public static void checkSuccessReply(NetconfMessage output) { + public static void checkSuccessReply(NetconfMessage output) throws NetconfDocumentedException { if(NetconfMessageUtil.isErrorMessage(output)) { throw new IllegalStateException(String.format("Response contains error: %s", XmlUtil.toString(output.getDocument()))); } diff --git a/opendaylight/netconf/config-netconf-connector/pom.xml b/opendaylight/netconf/config-netconf-connector/pom.xml index 2a0f0a97f7..c10f0a9089 100644 --- a/opendaylight/netconf/config-netconf-connector/pom.xml +++ b/opendaylight/netconf/config-netconf-connector/pom.xml @@ -105,7 +105,8 @@ org.opendaylight.controller.netconf.confignetconfconnector.transactions, org.opendaylight.controller.netconf.confignetconfconnector.util, org.opendaylight.controller.netconf.confignetconfconnector.osgi, - org.opendaylight.controller.config.util, + org.opendaylight.controller.config.util, + org.opendaylight.controller.netconf.confignetconfconnector.exception, com.google.common.base, com.google.common.collect, javax.annotation, @@ -119,6 +120,7 @@ org.opendaylight.controller.netconf.mapping.api, org.opendaylight.controller.netconf.util.mapping, org.opendaylight.controller.netconf.util.xml, + org.opendaylight.controller.netconf.util.exception, org.opendaylight.yangtools.yang.common, org.opendaylight.yangtools.yang.model.api, org.osgi.framework, @@ -128,7 +130,7 @@ com.google.common.io, org.opendaylight.yangtools.yang.model.api.type, org.opendaylight.yangtools.sal.binding.generator.spi, - org.opendaylight.yangtools.sal.binding.yang.types + org.opendaylight.yangtools.sal.binding.yang.types, diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/exception/NetconfConfigHandlingException.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/exception/NetconfConfigHandlingException.java new file mode 100644 index 0000000000..be44a71e06 --- /dev/null +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/exception/NetconfConfigHandlingException.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2013 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.controller.netconf.confignetconfconnector.exception; + +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; + +import java.util.Collections; +import java.util.Map; + +public class NetconfConfigHandlingException extends NetconfDocumentedException { + + public NetconfConfigHandlingException(final String message, final ErrorType errorType, final ErrorTag errorTag, + final ErrorSeverity errorSeverity) { + this(message, errorType, errorTag, errorSeverity, Collections.emptyMap()); + } + + public NetconfConfigHandlingException(final String message, final ErrorType errorType, final ErrorTag errorTag, + final ErrorSeverity errorSeverity, final Map errorInfo){ + super(message,errorType,errorTag,errorSeverity,errorInfo); + } +} diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/exception/NoTransactionFoundException.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/exception/NoTransactionFoundException.java new file mode 100644 index 0000000000..ebb8054c71 --- /dev/null +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/exception/NoTransactionFoundException.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2013 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.controller.netconf.confignetconfconnector.exception; + +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; + +import java.util.Collections; +import java.util.Map; + +public class NoTransactionFoundException extends NetconfDocumentedException { + + public NoTransactionFoundException(final String message, final ErrorType errorType, final ErrorTag errorTag, + final ErrorSeverity errorSeverity) { + this(message, errorType, errorTag, errorSeverity, Collections. emptyMap()); + } + + public NoTransactionFoundException(final String message, final ErrorType errorType, final ErrorTag errorTag, + final ErrorSeverity errorSeverity, final Map errorInfo){ + super(message,errorType,errorTag,errorSeverity,errorInfo); + } + +} diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/exception/OperationNotPermittedException.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/exception/OperationNotPermittedException.java new file mode 100644 index 0000000000..e0d63c1418 --- /dev/null +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/exception/OperationNotPermittedException.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2013 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.controller.netconf.confignetconfconnector.exception; + +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; + +import java.util.Collections; +import java.util.Map; + +public class OperationNotPermittedException extends NetconfDocumentedException { + + public OperationNotPermittedException(final String message, final ErrorType errorType, final ErrorTag errorTag, + final ErrorSeverity errorSeverity) { + this(message, errorType, errorTag, errorSeverity, Collections. emptyMap()); + } + + public OperationNotPermittedException(final String message, final ErrorType errorType, final ErrorTag errorTag, + final ErrorSeverity errorSeverity, final Map errorInfo){ + super(message,errorType,errorTag,errorSeverity,errorInfo); + } +} diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AbstractAttributeReadingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AbstractAttributeReadingStrategy.java index 7939112628..701e96ecd9 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AbstractAttributeReadingStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AbstractAttributeReadingStrategy.java @@ -8,6 +8,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.util.xml.XmlElement; import java.util.List; @@ -25,14 +26,14 @@ public abstract class AbstractAttributeReadingStrategy implements AttributeReadi } @Override - public AttributeConfigElement readElement(List configNodes) { - if (configNodes.size() == 0) + public AttributeConfigElement readElement(List configNodes) throws NetconfDocumentedException { + if (configNodes.size() == 0){ return AttributeConfigElement.createNullValue(postprocessNullableDefault(nullableDefault)); - + } return readElementHook(configNodes); } - abstract AttributeConfigElement readElementHook(List configNodes); + abstract AttributeConfigElement readElementHook(List configNodes) throws NetconfDocumentedException; protected Object postprocessNullableDefault(String nullableDefault) { return nullableDefault; diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ArrayAttributeReadingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ArrayAttributeReadingStrategy.java index 8f56961900..442c504cce 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ArrayAttributeReadingStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ArrayAttributeReadingStrategy.java @@ -9,6 +9,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml; import com.google.common.collect.Lists; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.util.xml.XmlElement; import java.util.List; @@ -27,7 +28,7 @@ public class ArrayAttributeReadingStrategy extends AbstractAttributeReadingStrat } @Override - AttributeConfigElement readElementHook(List configNodes) { + AttributeConfigElement readElementHook(List configNodes) throws NetconfDocumentedException { List innerList = Lists.newArrayList(); for (int i = 0; i < configNodes.size(); i++) { innerList.add(innerStrategy.readElement(Lists.newArrayList(configNodes.get(i))).getValue()); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AttributeReadingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AttributeReadingStrategy.java index 6dae839148..4e78370c93 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AttributeReadingStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AttributeReadingStrategy.java @@ -10,10 +10,11 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attri import java.util.List; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.util.xml.XmlElement; public interface AttributeReadingStrategy { - public abstract AttributeConfigElement readElement(List element); + public abstract AttributeConfigElement readElement(List element) throws NetconfDocumentedException; } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/CompositeAttributeReadingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/CompositeAttributeReadingStrategy.java index fdbfb98e1c..792fb28027 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/CompositeAttributeReadingStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/CompositeAttributeReadingStrategy.java @@ -11,6 +11,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attri import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.util.xml.XmlElement; import java.util.List; @@ -28,7 +29,7 @@ public class CompositeAttributeReadingStrategy extends AbstractAttributeReadingS } @Override - AttributeConfigElement readElementHook(List configNodes) { + AttributeConfigElement readElementHook(List configNodes) throws NetconfDocumentedException { Preconditions.checkState(configNodes.size() == 1, "This element should be present only once %s", configNodes); @@ -38,7 +39,8 @@ public class CompositeAttributeReadingStrategy extends AbstractAttributeReadingS List recognisedChildren = Lists.newArrayList(); for (Entry innerAttrEntry : innerStrategies.entrySet()) { - List childItem = complexElement.getChildElementsWithSameNamespace(innerAttrEntry.getKey()); + List childItem = null; + childItem = complexElement.getChildElementsWithSameNamespace(innerAttrEntry.getKey()); recognisedChildren.addAll(childItem); AttributeConfigElement resolvedInner = innerAttrEntry.getValue().readElement(childItem); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectNameAttributeReadingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectNameAttributeReadingStrategy.java index 7a4ba31255..5f44c16dca 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectNameAttributeReadingStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectNameAttributeReadingStrategy.java @@ -8,9 +8,12 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml; import com.google.common.base.Preconditions; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.ObjectNameAttributeMappingStrategy; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.List; import java.util.Map; @@ -18,13 +21,14 @@ import java.util.Map; public class ObjectNameAttributeReadingStrategy extends AbstractAttributeReadingStrategy { private static final Object PREFIX_SEPARATOR = ":"; + private static final Logger logger = LoggerFactory.getLogger(ObjectNameAttributeReadingStrategy.class); public ObjectNameAttributeReadingStrategy(String nullableDefault) { super(nullableDefault); } @Override - AttributeConfigElement readElementHook(List configNodes) { + AttributeConfigElement readElementHook(List configNodes) throws NetconfDocumentedException { XmlElement firstChild = configNodes.get(0); Preconditions.checkState(configNodes.size() == 1, "This element should be present only once " + firstChild @@ -34,8 +38,9 @@ public class ObjectNameAttributeReadingStrategy extends AbstractAttributeReading return AttributeConfigElement.create(getNullableDefault(), resolve(firstChild)); } - private ObjectNameAttributeMappingStrategy.MappedDependency resolve(XmlElement firstChild) { - XmlElement typeElement = firstChild.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY); + private ObjectNameAttributeMappingStrategy.MappedDependency resolve(XmlElement firstChild) throws NetconfDocumentedException{ + XmlElement typeElement = null; + typeElement = firstChild.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY); Map.Entry prefixNamespace = typeElement.findNamespaceOfTextContent(); String serviceName = checkPrefixAndExtractServiceName(typeElement, prefixNamespace); @@ -47,7 +52,7 @@ public class ObjectNameAttributeReadingStrategy extends AbstractAttributeReading dependencyName); } - public static String checkPrefixAndExtractServiceName(XmlElement typeElement, Map.Entry prefixNamespace) { + public static String checkPrefixAndExtractServiceName(XmlElement typeElement, Map.Entry prefixNamespace) throws NetconfDocumentedException { String serviceName = typeElement.getTextContent(); Preconditions.checkState(prefixNamespace.equals("") == false, "Service %s value not prefixed with namespace", diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleAttributeReadingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleAttributeReadingStrategy.java index 3765a13508..cb8f66081b 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleAttributeReadingStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleAttributeReadingStrategy.java @@ -9,12 +9,12 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml; import com.google.common.base.Preconditions; +import java.util.List; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.List; - public class SimpleAttributeReadingStrategy extends AbstractAttributeReadingStrategy { private static final Logger logger = LoggerFactory.getLogger(SimpleAttributeReadingStrategy.class); @@ -24,7 +24,7 @@ public class SimpleAttributeReadingStrategy extends AbstractAttributeReadingStra } @Override - AttributeConfigElement readElementHook(List configNodes) { + AttributeConfigElement readElementHook(List configNodes) throws NetconfDocumentedException { XmlElement xmlElement = configNodes.get(0); Preconditions.checkState(configNodes.size() == 1, "This element should be present only once " + xmlElement + " but was " + configNodes.size()); @@ -37,12 +37,17 @@ public class SimpleAttributeReadingStrategy extends AbstractAttributeReadingStra logger.warn("Ignoring exception caused by failure to read text element", e); } - Preconditions.checkNotNull(textContent, "This element should contain text %s", xmlElement); + if (null == textContent){ + throw new NetconfDocumentedException(String.format("This element should contain text %s", xmlElement), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.invalid_value, + NetconfDocumentedException.ErrorSeverity.error); + } return AttributeConfigElement.create(postprocessNullableDefault(getNullableDefault()), postprocessParsedValue(textContent)); } - protected String readElementContent(XmlElement xmlElement) { + protected String readElementContent(XmlElement xmlElement) throws NetconfDocumentedException { return xmlElement.getTextContent(); } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleIdentityRefAttributeReadingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleIdentityRefAttributeReadingStrategy.java index 1205597125..58f91a7dee 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleIdentityRefAttributeReadingStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleIdentityRefAttributeReadingStrategy.java @@ -15,6 +15,7 @@ import java.util.Map; import com.google.common.base.Preconditions; import com.google.common.collect.Maps; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.yangtools.yang.common.QName; @@ -32,7 +33,7 @@ public class SimpleIdentityRefAttributeReadingStrategy extends SimpleAttributeRe } @Override - protected String readElementContent(XmlElement xmlElement) { + protected String readElementContent(XmlElement xmlElement) throws NetconfDocumentedException { // TODO test Map.Entry namespaceOfTextContent = xmlElement.findNamespaceOfTextContent(); String content = xmlElement.getTextContent(); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java index decb091f86..bb5a67cb9c 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java @@ -23,6 +23,7 @@ import java.util.Set; import javax.management.ObjectName; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType; import org.opendaylight.controller.netconf.util.xml.XmlElement; @@ -147,7 +148,7 @@ public class Config { // TODO refactor, replace Map->Multimap with e.g. ConfigElementResolved // class - public Map> fromXmlModulesResolved(XmlElement xml, EditStrategyType defaultEditStrategyType, ServiceRegistryWrapper serviceTracker) { + public Map> fromXmlModulesResolved(XmlElement xml, EditStrategyType defaultEditStrategyType, ServiceRegistryWrapper serviceTracker) throws NetconfDocumentedException { Optional modulesElement = getModulesElement(xml); List moduleElements = getModulesElementList(modulesElement); @@ -156,7 +157,7 @@ public class Config { for (XmlElement moduleElement : moduleElements) { ResolvingStrategy resolvingStrategy = new ResolvingStrategy() { @Override - public ModuleElementResolved resolveElement(ModuleConfig moduleMapping, XmlElement moduleElement, ServiceRegistryWrapper serviceTracker, String instanceName, String moduleNamespace, EditStrategyType defaultStrategy) { + public ModuleElementResolved resolveElement(ModuleConfig moduleMapping, XmlElement moduleElement, ServiceRegistryWrapper serviceTracker, String instanceName, String moduleNamespace, EditStrategyType defaultStrategy) throws NetconfDocumentedException { return moduleMapping.fromXml(moduleElement, serviceTracker, instanceName, moduleNamespace, defaultStrategy, identityMap); } @@ -171,7 +172,7 @@ public class Config { * return a map containing namespace -> moduleName -> instanceName map. Attribute parsing is omitted. */ public Map> fromXmlModulesMap(XmlElement xml, - EditStrategyType defaultEditStrategyType, ServiceRegistryWrapper serviceTracker) { + EditStrategyType defaultEditStrategyType, ServiceRegistryWrapper serviceTracker) throws NetconfDocumentedException { Optional modulesElement = getModulesElement(xml); List moduleElements = getModulesElementList(modulesElement); @@ -201,7 +202,7 @@ public class Config { XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG); } - private List getModulesElementList(Optional modulesElement) { + private List getModulesElementList(Optional modulesElement) throws NetconfDocumentedException { List moduleElements; if (modulesElement.isPresent()) { @@ -214,11 +215,13 @@ public class Config { } private void resolveModule(Map> retVal, ServiceRegistryWrapper serviceTracker, - XmlElement moduleElement, EditStrategyType defaultStrategy, ResolvingStrategy resolvingStrategy) { - XmlElement typeElement = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY); + XmlElement moduleElement, EditStrategyType defaultStrategy, ResolvingStrategy resolvingStrategy) throws NetconfDocumentedException { + XmlElement typeElement = null; + typeElement = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY); Entry prefixToNamespace = typeElement.findNamespaceOfTextContent(); String moduleNamespace = prefixToNamespace.getValue(); - XmlElement nameElement = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.NAME_KEY); + XmlElement nameElement = null; + nameElement = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.NAME_KEY); String instanceName = nameElement.getTextContent(); String factoryNameWithPrefix = typeElement.getTextContent(); String prefixOrEmptyString = prefixToNamespace.getKey(); @@ -238,7 +241,7 @@ public class Config { innerMap.put(factoryName, resolvedElement); } - public Services fromXmlServices(XmlElement xml) { + public Services fromXmlServices(XmlElement xml) throws NetconfDocumentedException { Optional servicesElement = getServicesElement(xml); Services services; @@ -256,7 +259,7 @@ public class Config { XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG); } - public static void checkUnrecognisedChildren(XmlElement parent) { + public static void checkUnrecognisedChildren(XmlElement parent) throws NetconfDocumentedException { Optional servicesOpt = getServicesElement(parent); Optional modulesOpt = getModulesElement(parent); @@ -298,6 +301,6 @@ public class Config { private interface ResolvingStrategy { public T resolveElement(ModuleConfig moduleMapping, XmlElement moduleElement, ServiceRegistryWrapper serviceTracker, - String instanceName, String moduleNamespace, EditStrategyType defaultStrategy); + String instanceName, String moduleNamespace, EditStrategyType defaultStrategy) throws NetconfDocumentedException; } } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java index a940be7e77..1da9fabdb3 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java @@ -9,13 +9,13 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config; import com.google.common.base.Optional; -import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import org.opendaylight.controller.config.util.ConfigRegistryClient; import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry; import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeReadingStrategy; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.ObjectXmlReader; @@ -131,14 +131,16 @@ public final class InstanceConfig { } public InstanceConfigElementResolved fromXml(XmlElement moduleElement, ServiceRegistryWrapper services, String moduleNamespace, - EditStrategyType defaultStrategy, Multimap providedServices, Map> identityMap) { + EditStrategyType defaultStrategy, Multimap providedServices, Map> identityMap) throws NetconfDocumentedException { Map retVal = Maps.newHashMap(); Map strats = new ObjectXmlReader().prepareReading(yangToAttrConfig, identityMap); List recognisedChildren = Lists.newArrayList(); - XmlElement type = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY); - XmlElement name = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.NAME_KEY); + XmlElement type = null; + XmlElement name = null; + type = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY); + name = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.NAME_KEY); List typeAndName = Lists.newArrayList(type, name); for (Entry readStratEntry : strats.entrySet()) { @@ -163,7 +165,7 @@ public final class InstanceConfig { } private List getConfigNodes(XmlElement moduleElement, String moduleNamespace, String name, - List recognisedChildren, List typeAndName) { + List recognisedChildren, List typeAndName) throws NetconfDocumentedException { List foundConfigNodes = moduleElement.getChildElementsWithinNamespace(name, moduleNamespace); if (foundConfigNodes.isEmpty()) { logger.debug("No config nodes {}:{} found in {}", moduleNamespace, name, moduleElement); @@ -181,9 +183,13 @@ public final class InstanceConfig { List foundWithoutNamespaceNodes = moduleElement.getChildElementsWithinNamespace(name, XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG); foundWithoutNamespaceNodes.removeAll(typeAndName); - Preconditions.checkState(foundWithoutNamespaceNodes.isEmpty(), - "Element %s present multiple times with different namespaces: %s, %s", name, foundConfigNodes, - foundWithoutNamespaceNodes); + if (!foundWithoutNamespaceNodes.isEmpty()){ + throw new NetconfDocumentedException(String.format("Element %s present multiple times with different namespaces: %s, %s", name, foundConfigNodes, + foundWithoutNamespaceNodes), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.invalid_value, + NetconfDocumentedException.ErrorSeverity.error); + } } recognisedChildren.addAll(foundConfigNodes); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfigElementResolved.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfigElementResolved.java index 0bb4191bf2..0d55902b12 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfigElementResolved.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfigElementResolved.java @@ -8,8 +8,9 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config; -import com.google.common.base.Preconditions; import com.google.common.collect.Multimap; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.confignetconfconnector.exception.OperationNotPermittedException; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfigStrategy; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfigXmlParser; @@ -27,8 +28,9 @@ public class InstanceConfigElementResolved { private final Map configuration; private final Multimap providedServices; - public InstanceConfigElementResolved(String currentStrategy, Map configuration, EditStrategyType defaultStrategy, Multimap providedServices) { - EditStrategyType valueOf = parseStrategy(currentStrategy, defaultStrategy); + public InstanceConfigElementResolved(String currentStrategy, Map configuration, EditStrategyType defaultStrategy, Multimap providedServices) throws NetconfDocumentedException { + EditStrategyType valueOf = null; + valueOf = parseStrategy(currentStrategy, defaultStrategy); this.editStrategy = valueOf; this.configuration = configuration; this.providedServices = providedServices; @@ -41,18 +43,19 @@ public class InstanceConfigElementResolved { } - static EditStrategyType parseStrategy(String currentStrategy, EditStrategyType defaultStrategy) { - EditStrategyType parsedStrategy = EditStrategyType.valueOf(currentStrategy); - if (defaultStrategy.isEnforcing()) { - Preconditions - .checkArgument( - parsedStrategy == defaultStrategy, - "With " - + defaultStrategy - + " as " - + EditConfigXmlParser.DEFAULT_OPERATION_KEY - + " operations on module elements are not permitted since the default option is restrictive"); + static EditStrategyType parseStrategy(String currentStrategy, EditStrategyType defaultStrategy) throws OperationNotPermittedException { + if (null == currentStrategy || currentStrategy.equals("")){ + throw new OperationNotPermittedException(String.format("With " + + defaultStrategy + + " as " + + EditConfigXmlParser.DEFAULT_OPERATION_KEY + + " operations on module elements are not permitted since the default option is restrictive"), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.operation_failed, + NetconfDocumentedException.ErrorSeverity.error); } + EditStrategyType parsedStrategy = EditStrategyType.valueOf(currentStrategy); + EditStrategyType.compareParsedStrategyToDefaultEnforcing(parsedStrategy,defaultStrategy); return parsedStrategy; } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleConfig.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleConfig.java index dbaa7895d3..f3d75d07be 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleConfig.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleConfig.java @@ -15,6 +15,7 @@ import java.util.Map; import javax.management.ObjectName; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType; import org.opendaylight.controller.netconf.util.xml.XmlElement; @@ -90,7 +91,7 @@ public class ModuleConfig { } public ModuleElementResolved fromXml(XmlElement moduleElement, ServiceRegistryWrapper depTracker, String instanceName, - String moduleNamespace, EditStrategyType defaultStrategy, Map> identityMap) { + String moduleNamespace, EditStrategyType defaultStrategy, Map> identityMap) throws NetconfDocumentedException { InstanceConfigElementResolved ice = instanceConfig.fromXml(moduleElement, depTracker, moduleNamespace, defaultStrategy, providedServices, identityMap); return new ModuleElementResolved(instanceName, ice); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleElementDefinition.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleElementDefinition.java index 9111701ba0..d1c3ebeb0d 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleElementDefinition.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleElementDefinition.java @@ -8,10 +8,13 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config; +import org.opendaylight.controller.netconf.confignetconfconnector.exception.OperationNotPermittedException; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfigStrategy; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.MissingInstanceHandlingStrategy; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.NoneEditConfigStrategy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ModuleElementDefinition { @@ -20,13 +23,24 @@ public class ModuleElementDefinition { private final String instanceName; private final EditStrategyType editStrategy; + private static final Logger logger = LoggerFactory.getLogger(ModuleElementDefinition.class); public ModuleElementDefinition(String instanceName, String currentStrategy, EditStrategyType defaultStrategy) { this.instanceName = instanceName; + EditStrategyType _edStrategy = null; + try { + _edStrategy = InstanceConfigElementResolved.parseStrategy(currentStrategy, defaultStrategy); + } catch (OperationNotPermittedException e) { + _edStrategy = defaultStrategy; + logger.warn("Operation not permitted on current strategy {} while default strategy is {}. Element definition strategy set to default.", + currentStrategy, + defaultStrategy, + e); + } if (currentStrategy == null || currentStrategy.isEmpty()) - this.editStrategy = defaultStrategy; - else - this.editStrategy = InstanceConfigElementResolved.parseStrategy(currentStrategy, defaultStrategy); + _edStrategy = defaultStrategy; + + this.editStrategy = _edStrategy; } public String getInstanceName() { diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Services.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Services.java index 9767b3f056..f9df717008 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Services.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Services.java @@ -17,6 +17,7 @@ import java.util.regex.Pattern; import javax.management.ObjectName; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.ObjectNameAttributeReadingStrategy; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; @@ -86,7 +87,7 @@ public final class Services { // TODO support edit strategies on services - public static Services fromXml(XmlElement xml) { + public static Services fromXml(XmlElement xml) throws NetconfDocumentedException { Map>> retVal = Maps.newHashMap(); List services = xml.getChildElements(SERVICE_KEY); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/InstanceRuntimeRpc.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/InstanceRuntimeRpc.java index b7f5fc780b..d63d8a139d 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/InstanceRuntimeRpc.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/InstanceRuntimeRpc.java @@ -12,6 +12,7 @@ import com.google.common.collect.Maps; import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry.Rpc; import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc; import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeReadingStrategy; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.ObjectXmlReader; @@ -67,7 +68,7 @@ public final class InstanceRuntimeRpc { } } - public Map fromXml(XmlElement configRootNode) { + public Map fromXml(XmlElement configRootNode) throws NetconfDocumentedException { Map retVal = Maps.newHashMap(); // FIXME add identity map to runtime data diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Commit.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Commit.java index 561aab9052..d49fe1a116 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Commit.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Commit.java @@ -8,17 +8,11 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations; -import java.util.HashMap; -import java.util.Map; - import org.opendaylight.controller.config.api.ConflictingVersionException; import org.opendaylight.controller.config.api.ValidationException; import org.opendaylight.controller.config.api.jmx.CommitStatus; import org.opendaylight.controller.config.util.ConfigRegistryClient; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; -import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity; -import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag; -import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType; import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; @@ -42,7 +36,7 @@ public class Commit extends AbstractConfigNetconfOperation { this.transactionProvider = transactionProvider; } - private static void checkXml(XmlElement xml) { + private static void checkXml(XmlElement xml) throws NetconfDocumentedException { xml.checkName(XmlNetconfConstants.COMMIT); xml.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); } @@ -54,25 +48,14 @@ public class Commit extends AbstractConfigNetconfOperation { @Override protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException { - checkXml(xml); + checkXml(xml); CommitStatus status; try { status = this.transactionProvider.commitTransaction(); - } catch (final IllegalStateException e) { - // TODO Illegal state thrown when no transaction yet for user - // Throw other exception type, or create transaction automatically - logger.warn("Commit failed: ", e); - final Map errorInfo = new HashMap<>(); - errorInfo.put(ErrorTag.operation_failed.name(), - "Operation failed. Use 'get-config' or 'edit-config' before triggering 'commit' operation"); - throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.application, ErrorTag.operation_failed, - ErrorSeverity.error, errorInfo); - } catch (ValidationException e) { + logger.trace("Datastore {} committed successfully: {}", Datastore.candidate, status); + } catch (ConflictingVersionException | ValidationException e) { throw NetconfDocumentedException.wrap(e); - } catch (ConflictingVersionException e) { - throw NetconfDocumentedException.wrap(e); - } logger.trace("Datastore {} committed successfully: {}", Datastore.candidate, status); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/DiscardChanges.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/DiscardChanges.java index 639d4dac72..96a43b104d 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/DiscardChanges.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/DiscardChanges.java @@ -6,11 +6,9 @@ * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.controller.netconf.confignetconfconnector.operations; - -import java.util.HashMap; -import java.util.Map; + package org.opendaylight.controller.netconf.confignetconfconnector.operations; +import com.google.common.base.Optional; import org.opendaylight.controller.config.util.ConfigRegistryClient; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity; @@ -25,7 +23,9 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import com.google.common.base.Optional; +import java.util.HashMap; +import java.util.Map; + public class DiscardChanges extends AbstractConfigNetconfOperation { @@ -41,7 +41,7 @@ public class DiscardChanges extends AbstractConfigNetconfOperation { this.transactionProvider = transactionProvider; } - private static void fromXml(XmlElement xml) { + private static void fromXml(XmlElement xml) throws NetconfDocumentedException { xml.checkName(DISCARD); xml.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); } @@ -53,21 +53,10 @@ public class DiscardChanges extends AbstractConfigNetconfOperation { @Override protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException { - try { - fromXml(xml); - } catch (final IllegalArgumentException e) { - //FIXME where can IllegalStateException be thrown? - logger.warn("Rpc error: {}", ErrorTag.bad_attribute, e); - final Map errorInfo = new HashMap<>(); - errorInfo.put(ErrorTag.bad_attribute.name(), e.getMessage()); - throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.rpc, ErrorTag.bad_attribute, - ErrorSeverity.error, errorInfo); - } - + fromXml(xml); try { this.transactionProvider.abortTransaction(); } catch (final IllegalStateException e) { - //FIXME where can IllegalStateException be thrown? logger.warn("Abort failed: ", e); final Map errorInfo = new HashMap<>(); errorInfo @@ -78,6 +67,7 @@ public class DiscardChanges extends AbstractConfigNetconfOperation { } logger.trace("Changes discarded successfully from datastore {}", Datastore.candidate); + return XmlUtil.createElement(document, XmlNetconfConstants.OK, Optional.absent()); } } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Validate.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Validate.java index 642c4456a8..1a7d50e5fa 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Validate.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Validate.java @@ -8,9 +8,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations; -import java.util.HashMap; -import java.util.Map; - +import com.google.common.base.Optional; import org.opendaylight.controller.config.api.ValidationException; import org.opendaylight.controller.config.util.ConfigRegistryClient; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; @@ -26,8 +24,8 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; +import java.util.HashMap; +import java.util.Map; public class Validate extends AbstractConfigNetconfOperation { @@ -43,7 +41,7 @@ public class Validate extends AbstractConfigNetconfOperation { this.transactionProvider = transactionProvider; } - private void checkXml(XmlElement xml) { + private void checkXml(XmlElement xml) throws NetconfDocumentedException { xml.checkName(VALIDATE); xml.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); @@ -55,8 +53,10 @@ public class Validate extends AbstractConfigNetconfOperation { String datastoreValue = sourceChildNode.getName(); Datastore sourceDatastore = Datastore.valueOf(datastoreValue); - Preconditions.checkState(sourceDatastore == Datastore.candidate, "Only " + Datastore.candidate - + " is supported as source for " + VALIDATE + " but was " + datastoreValue); + if (sourceDatastore != Datastore.candidate){ + throw new NetconfDocumentedException( "Only " + Datastore.candidate + + " is supported as source for " + VALIDATE + " but was " + datastoreValue,ErrorType.application,ErrorTag.data_missing,ErrorSeverity.error); + } } @Override @@ -66,24 +66,7 @@ public class Validate extends AbstractConfigNetconfOperation { @Override protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException { - try { - checkXml(xml); - } catch (IllegalStateException e) { - //FIXME where can IllegalStateException be thrown? I see precondition that guards for programming bugs.. - logger.warn("Rpc error: {}", ErrorTag.missing_attribute, e); - final Map errorInfo = new HashMap<>(); - errorInfo.put(ErrorTag.missing_attribute.name(), "Missing value of datastore attribute"); - throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.rpc, ErrorTag.missing_attribute, - ErrorSeverity.error, errorInfo); - } catch (final IllegalArgumentException e) { - // FIXME use checked exception if it has domain meaning - logger.warn("Rpc error: {}", ErrorTag.bad_attribute, e); - final Map errorInfo = new HashMap<>(); - errorInfo.put(ErrorTag.bad_attribute.name(), e.getMessage()); - throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.rpc, ErrorTag.bad_attribute, - ErrorSeverity.error, errorInfo); - } - + checkXml(xml); try { transactionProvider.validateTransaction(); } catch (ValidationException e) { diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/AbstractEditConfigStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/AbstractEditConfigStrategy.java index 1d37fcd493..820f8ff772 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/AbstractEditConfigStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/AbstractEditConfigStrategy.java @@ -9,6 +9,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig; import org.opendaylight.controller.config.util.ConfigTransactionClient; +import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper; import org.slf4j.Logger; @@ -24,7 +25,7 @@ public abstract class AbstractEditConfigStrategy implements EditConfigStrategy { @Override public void executeConfiguration(String module, String instance, Map configuration, - ConfigTransactionClient ta, ServiceRegistryWrapper services) { + ConfigTransactionClient ta, ServiceRegistryWrapper services) throws NetconfConfigHandlingException { try { ObjectName on = ta.lookupConfigBean(module, instance); @@ -40,9 +41,9 @@ public abstract class AbstractEditConfigStrategy implements EditConfigStrategy { // edit configs should not handle missing abstract void handleMissingInstance(Map configuration, ConfigTransactionClient ta, - String module, String instance, ServiceRegistryWrapper services); + String module, String instance, ServiceRegistryWrapper services) throws NetconfConfigHandlingException; abstract void executeStrategy(Map configuration, ConfigTransactionClient ta, - ObjectName objectName, ServiceRegistryWrapper services); + ObjectName objectName, ServiceRegistryWrapper services) throws NetconfConfigHandlingException; } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/DeleteEditConfigStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/DeleteEditConfigStrategy.java index 13e8c30211..e88863c685 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/DeleteEditConfigStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/DeleteEditConfigStrategy.java @@ -11,6 +11,8 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.ed import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import org.opendaylight.controller.config.util.ConfigTransactionClient; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper; import org.slf4j.Logger; @@ -36,17 +38,24 @@ public class DeleteEditConfigStrategy extends AbstractEditConfigStrategy { @Override void handleMissingInstance(Map configuration, ConfigTransactionClient ta, - String module, String instance, ServiceRegistryWrapper services) { - throw new IllegalStateException("Unable to delete " + module + ":" + instance + " , ServiceInstance not found"); + String module, String instance, ServiceRegistryWrapper services) throws NetconfConfigHandlingException { + throw new NetconfConfigHandlingException(String.format("Unable to delete %s : %s , ServiceInstance not found", module ,instance), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.operation_failed, + NetconfDocumentedException.ErrorSeverity.error); } @Override - void executeStrategy(Map configuration, ConfigTransactionClient ta, ObjectName on, ServiceRegistryWrapper services) { + void executeStrategy(Map configuration, ConfigTransactionClient ta, ObjectName on, ServiceRegistryWrapper services) throws NetconfConfigHandlingException { try { ta.destroyModule(on); logger.debug("ServiceInstance {} deleted successfully", on); } catch (InstanceNotFoundException e) { - throw new IllegalStateException("Unable to delete " + on, e); + throw new NetconfConfigHandlingException( + String.format("Unable to delete %s because of exception %s" + on, e.getMessage()), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.operation_failed, + NetconfDocumentedException.ErrorSeverity.error); } } } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java index 0cc9d1153f..428ddb3b74 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java @@ -8,15 +8,11 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import javax.management.InstanceNotFoundException; -import javax.management.ObjectName; - +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; import org.opendaylight.controller.config.api.ValidationException; import org.opendaylight.controller.config.util.ConfigRegistryClient; import org.opendaylight.controller.config.util.ConfigTransactionClient; @@ -25,6 +21,7 @@ import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity; import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag; import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType; +import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfig; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfigElementResolved; @@ -46,11 +43,12 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.collect.Maps; -import com.google.common.collect.Multimap; +import javax.management.InstanceNotFoundException; +import javax.management.ObjectName; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; public class EditConfig extends AbstractConfigNetconfOperation { @@ -71,7 +69,7 @@ public class EditConfig extends AbstractConfigNetconfOperation { @VisibleForTesting Element getResponseInternal(final Document document, - final EditConfigXmlParser.EditConfigExecution editConfigExecution) throws NetconfDocumentedException { + final EditConfigXmlParser.EditConfigExecution editConfigExecution) throws NetconfDocumentedException, NetconfConfigHandlingException { if (editConfigExecution.shouldTest()) { executeTests(configRegistryClient, editConfigExecution); @@ -88,19 +86,7 @@ public class EditConfig extends AbstractConfigNetconfOperation { private void executeSet(ConfigRegistryClient configRegistryClient, EditConfigXmlParser.EditConfigExecution editConfigExecution) throws NetconfDocumentedException { - try { - set(configRegistryClient, editConfigExecution); - - } catch (IllegalStateException e) { - //FIXME: when can IllegalStateException be thrown? - // JmxAttributeValidationException is wrapped in DynamicWritableWrapper with ValidationException - // ValidationException is not thrown until validate or commit is issued - logger.warn("Set phase for {} failed", EditConfigXmlParser.EDIT_CONFIG, e); - final Map errorInfo = new HashMap<>(); - errorInfo.put(ErrorTag.operation_failed.name(), e.getMessage()); - throw new NetconfDocumentedException("Test phase: " + e.getMessage(), e, ErrorType.application, - ErrorTag.operation_failed, ErrorSeverity.error, errorInfo); - } + set(configRegistryClient, editConfigExecution); logger.debug("Set phase for {} operation successful", EditConfigXmlParser.EDIT_CONFIG); } @@ -108,8 +94,7 @@ public class EditConfig extends AbstractConfigNetconfOperation { EditConfigExecution editConfigExecution) throws NetconfDocumentedException { try { test(configRegistryClient, editConfigExecution, editConfigExecution.getDefaultStrategy()); - } catch (IllegalStateException | ValidationException e) { - //FIXME: when can IllegalStateException be thrown? + } catch (final ValidationException e) { logger.warn("Test phase for {} failed", EditConfigXmlParser.EDIT_CONFIG, e); final Map errorInfo = new HashMap<>(); errorInfo.put(ErrorTag.operation_failed.name(), e.getMessage()); @@ -120,10 +105,9 @@ public class EditConfig extends AbstractConfigNetconfOperation { } private void test(ConfigRegistryClient configRegistryClient, EditConfigExecution execution, - EditStrategyType editStrategyType) throws ValidationException { + EditStrategyType editStrategyType) throws ValidationException, NetconfDocumentedException { ObjectName taON = transactionProvider.getTestTransaction(); try { - // default strategy = replace wipes config if (editStrategyType == EditStrategyType.replace) { transactionProvider.wipeTestTransaction(taON); @@ -141,7 +125,7 @@ public class EditConfig extends AbstractConfigNetconfOperation { } private void set(ConfigRegistryClient configRegistryClient, - EditConfigXmlParser.EditConfigExecution editConfigExecution) { + EditConfigXmlParser.EditConfigExecution editConfigExecution) throws NetconfDocumentedException { ObjectName taON = transactionProvider.getOrCreateTransaction(); // default strategy = replace wipes config @@ -156,7 +140,7 @@ public class EditConfig extends AbstractConfigNetconfOperation { setOnTransaction(ta, editConfigExecution); } - private void setServicesOnTransaction(ConfigTransactionClient ta, EditConfigExecution execution) { + private void setServicesOnTransaction(ConfigTransactionClient ta, EditConfigExecution execution) throws NetconfDocumentedException { Services services = execution.getServices(); @@ -177,7 +161,10 @@ public class EditConfig extends AbstractConfigNetconfOperation { logger.debug("Saving service {} with on {} under name {} with service on {}", qnameOfService, on, refName, saved); } catch (InstanceNotFoundException e) { - throw new IllegalStateException("Unable to save ref name " + refName + " for instance " + on, e); + throw new NetconfDocumentedException(String.format("Unable to save ref name " + refName + " for instance " + on, e), + ErrorType.application, + ErrorTag.operation_failed, + ErrorSeverity.error); } } } @@ -188,11 +175,11 @@ public class EditConfig extends AbstractConfigNetconfOperation { return ta.getServiceInterfaceName(namespace, serviceName); } - private void setOnTransaction(ConfigTransactionClient ta, EditConfigExecution execution) { + private void setOnTransaction(ConfigTransactionClient ta, EditConfigExecution execution) throws NetconfDocumentedException { for (Multimap modulesToResolved : execution.getResolvedXmlElements(ta).values()) { - for (Entry moduleToResolved : modulesToResolved.entries()) { + for (Map.Entry moduleToResolved : modulesToResolved.entries()) { String moduleName = moduleToResolved.getKey(); ModuleElementResolved moduleElementResolved = moduleToResolved.getValue(); @@ -206,10 +193,10 @@ public class EditConfig extends AbstractConfigNetconfOperation { } private void handleMisssingInstancesOnTransaction(ConfigTransactionClient ta, - EditConfigExecution execution) { + EditConfigExecution execution) throws NetconfDocumentedException { for (Multimap modulesToResolved : execution.getModulesDefinition(ta).values()) { - for (Entry moduleToResolved : modulesToResolved.entries()) { + for (Map.Entry moduleToResolved : modulesToResolved.entries()) { String moduleName = moduleToResolved.getKey(); ModuleElementDefinition moduleElementDefinition = moduleToResolved.getValue(); @@ -289,7 +276,7 @@ public class EditConfig extends AbstractConfigNetconfOperation { Map> namespaceToModuleNameToModuleConfig = Maps.newHashMap(); for (String namespace : mBeanEntries.keySet()) { - for (Entry moduleNameToMbe : mBeanEntries.get(namespace).entrySet()) { + for (Map.Entry moduleNameToMbe : mBeanEntries.get(namespace).entrySet()) { String moduleName = moduleNameToMbe.getKey(); ModuleMXBeanEntry moduleMXBeanEntry = moduleNameToMbe.getValue(); @@ -320,29 +307,11 @@ public class EditConfig extends AbstractConfigNetconfOperation { EditConfigXmlParser.EditConfigExecution editConfigExecution; Config cfg = getConfigMapping(configRegistryClient, yangStoreSnapshot); - try { - editConfigExecution = editConfigXmlParser.fromXml(xml, cfg, transactionProvider, configRegistryClient); - } catch (IllegalStateException e) { - logger.warn("Error parsing xml", e); - final Map errorInfo = new HashMap<>(); - errorInfo.put(ErrorTag.missing_attribute.name(), "Error parsing xml: " + e.getMessage()); - throw new NetconfDocumentedException(e.getMessage(), ErrorType.rpc, ErrorTag.missing_attribute, - ErrorSeverity.error, errorInfo); - } catch (final IllegalArgumentException e) { - logger.warn("Error parsing xml", e); - final Map errorInfo = new HashMap<>(); - errorInfo.put(ErrorTag.bad_attribute.name(), e.getMessage()); - throw new NetconfDocumentedException(e.getMessage(), ErrorType.rpc, ErrorTag.bad_attribute, - ErrorSeverity.error, errorInfo); - } catch (final UnsupportedOperationException e) { - logger.warn("Unsupported", e); - final Map errorInfo = new HashMap<>(); - errorInfo.put(ErrorTag.operation_not_supported.name(), "Unsupported option for 'edit-config'"); - throw new NetconfDocumentedException(e.getMessage(), ErrorType.application, - ErrorTag.operation_not_supported, ErrorSeverity.error, errorInfo); - } + editConfigExecution = editConfigXmlParser.fromXml(xml, cfg, transactionProvider, configRegistryClient); - return getResponseInternal(document, editConfigExecution); + Element responseInternal; + responseInternal = getResponseInternal(document, editConfigExecution); + return responseInternal; } } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigStrategy.java index cebcb0239b..8538e40bcd 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigStrategy.java @@ -9,6 +9,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig; import org.opendaylight.controller.config.util.ConfigTransactionClient; +import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper; @@ -17,6 +18,6 @@ import java.util.Map; public interface EditConfigStrategy { void executeConfiguration(String module, String instance, Map configuration, - ConfigTransactionClient ta, ServiceRegistryWrapper services); + ConfigTransactionClient ta, ServiceRegistryWrapper services) throws NetconfConfigHandlingException; } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigXmlParser.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigXmlParser.java index e481bbe57f..de6979565e 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigXmlParser.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigXmlParser.java @@ -10,7 +10,6 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.ed import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; -import com.google.common.base.Preconditions; import com.google.common.collect.Multimap; import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry; import org.opendaylight.controller.config.util.ConfigRegistryClient; @@ -22,6 +21,8 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services; import org.opendaylight.controller.netconf.confignetconfconnector.operations.Datastore; import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider; +import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException; +import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; import org.slf4j.Logger; @@ -55,15 +56,30 @@ public class EditConfigXmlParser { xml.checkName(EditConfigXmlParser.EDIT_CONFIG); xml.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); - XmlElement targetElement = xml.getOnlyChildElementWithSameNamespace(EditConfigXmlParser.TARGET_KEY); - XmlElement targetChildNode = targetElement.getOnlyChildElementWithSameNamespace(); + + XmlElement targetElement = null; + XmlElement targetChildNode = null; + try { + targetElement = xml.getOnlyChildElementWithSameNamespace(EditConfigXmlParser.TARGET_KEY); + targetChildNode = targetElement.getOnlyChildElementWithSameNamespace(); + } catch (final MissingNameSpaceException | UnexpectedNamespaceException e) { + logger.trace("Can't get only child element with same namespace due to {}",e); + throw NetconfDocumentedException.wrap(e); + } String datastoreValue = targetChildNode.getName(); Datastore targetDatastore = Datastore.valueOf(datastoreValue); logger.debug("Setting {} to '{}'", EditConfigXmlParser.TARGET_KEY, targetDatastore); // check target - Preconditions.checkArgument(targetDatastore == Datastore.candidate, - "Only %s datastore supported for edit config but was: %s", Datastore.candidate, targetDatastore); + if (targetDatastore != Datastore.candidate){ + throw new NetconfDocumentedException(String.format( + "Only %s datastore supported for edit config but was: %s", + Datastore.candidate, + targetDatastore), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.invalid_value, + NetconfDocumentedException.ErrorSeverity.error); + } // Test option TestOption testOption; @@ -96,7 +112,13 @@ public class EditConfigXmlParser { editStrategyType = EditStrategyType.valueOf(mergeStrategyString); } - XmlElement configElement = xml.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.CONFIG_KEY); + XmlElement configElement = null; + try { + configElement = xml.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.CONFIG_KEY); + } catch (MissingNameSpaceException e) { + logger.trace("Can't get only child element with same namespace due to {}",e); + throw NetconfDocumentedException.wrap(e); + } return new EditConfigXmlParser.EditConfigExecution(cfgMapping, configElement, testOption, editStrategyType); } @@ -134,7 +156,7 @@ public class EditConfigXmlParser { private final Config configResolver; private final XmlElement configElement; - EditConfigExecution(Config configResolver, XmlElement configElement, TestOption testOption, EditStrategyType defaultStrategy) { + EditConfigExecution(Config configResolver, XmlElement configElement, TestOption testOption, EditStrategyType defaultStrategy) throws NetconfDocumentedException { Config.checkUnrecognisedChildren(configElement); this.configResolver = configResolver; this.configElement = configElement; @@ -151,7 +173,7 @@ public class EditConfigXmlParser { return testOption == TestOption.set || testOption == TestOption.testThenSet; } - Map> getResolvedXmlElements(ServiceReferenceReadableRegistry serviceRegistry) { + Map> getResolvedXmlElements(ServiceReferenceReadableRegistry serviceRegistry) throws NetconfDocumentedException { return configResolver.fromXmlModulesResolved(configElement, defaultEditStrategyType, getServiceRegistryWrapper(serviceRegistry)); } @@ -160,7 +182,7 @@ public class EditConfigXmlParser { return new ServiceRegistryWrapper(serviceRegistry); } - Map> getModulesDefinition(ServiceReferenceReadableRegistry serviceRegistry) { + Map> getModulesDefinition(ServiceReferenceReadableRegistry serviceRegistry) throws NetconfDocumentedException { return configResolver.fromXmlModulesMap(configElement, defaultEditStrategyType, getServiceRegistryWrapper(serviceRegistry)); } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditStrategyType.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditStrategyType.java index 06560b2d27..2f41defac8 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditStrategyType.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditStrategyType.java @@ -9,6 +9,8 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig; import com.google.common.collect.Multimap; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.confignetconfconnector.exception.OperationNotPermittedException; import java.util.EnumSet; import java.util.Set; @@ -40,7 +42,22 @@ public enum EditStrategyType { + this); } } + public static void compareParsedStrategyToDefaultEnforcing(EditStrategyType parsedStrategy, + EditStrategyType defaultStrategy) throws OperationNotPermittedException { + if (defaultStrategy.isEnforcing()) { + if (parsedStrategy != defaultStrategy){ + throw new OperationNotPermittedException(String.format("With " + + defaultStrategy + + " as " + + EditConfigXmlParser.DEFAULT_OPERATION_KEY + + " operations on module elements are not permitted since the default option is restrictive"), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.operation_failed, + NetconfDocumentedException.ErrorSeverity.error); + } + } + } public EditConfigStrategy getFittingStrategy(Multimap providedServices) { switch (this) { case merge: diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MergeEditConfigStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MergeEditConfigStrategy.java index f2e2b193a8..0a72547d78 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MergeEditConfigStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MergeEditConfigStrategy.java @@ -12,6 +12,8 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; import org.opendaylight.controller.config.util.ConfigTransactionClient; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper; import org.slf4j.Logger; @@ -38,10 +40,14 @@ public class MergeEditConfigStrategy extends AbstractEditConfigStrategy { @Override void handleMissingInstance(Map configuration, ConfigTransactionClient ta, - String module, String instance, ServiceRegistryWrapper services) { - throw new IllegalStateException( - "Unable to handle missing instance, no missing instances should appear at this point, missing: " - + module + ":" + instance); + String module, String instance, ServiceRegistryWrapper services) throws NetconfConfigHandlingException { + throw new NetconfConfigHandlingException( + String.format("Unable to handle missing instance, no missing instances should appear at this point, missing: %s : %s ", + module, + instance), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.operation_failed, + NetconfDocumentedException.ErrorSeverity.error); } private void addRefNames(ServiceRegistryWrapper services, Multimap providedServices, ConfigTransactionClient ta, ObjectName on) throws InstanceNotFoundException { @@ -59,11 +65,14 @@ public class MergeEditConfigStrategy extends AbstractEditConfigStrategy { } @Override - void executeStrategy(Map configuration, ConfigTransactionClient ta, ObjectName on, ServiceRegistryWrapper services) { + void executeStrategy(Map configuration, ConfigTransactionClient ta, ObjectName on, ServiceRegistryWrapper services) throws NetconfConfigHandlingException { try { addRefNames(services, providedServices, ta, on); } catch (InstanceNotFoundException e) { - throw new IllegalStateException("Unable to save default ref name for instance " + on, e); + throw new NetconfConfigHandlingException(String.format("Unable to save default ref name for instance %s. Instance was not found.",e), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.operation_failed, + NetconfDocumentedException.ErrorSeverity.error); } for (Entry configAttributeEntry : configuration.entrySet()) { @@ -79,8 +88,13 @@ public class MergeEditConfigStrategy extends AbstractEditConfigStrategy { ta.setAttribute(on, ace.getJmxName(), new Attribute(ace.getJmxName(), value)); logger.debug("Attribute {} set to {} for {}", configAttributeEntry.getKey(), value, on); } catch (Exception e) { - throw new IllegalStateException("Unable to set attributes for " + on + ", Error with attribute " - + configAttributeEntry.getKey() + ":" + configAttributeEntry.getValue(), e); + throw new NetconfConfigHandlingException(String.format("Unable to set attributes for %s, Error with attribute %s : %s ", + on, + configAttributeEntry.getKey(), + configAttributeEntry.getValue()), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.operation_failed, + NetconfDocumentedException.ErrorSeverity.error); } } } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MissingInstanceHandlingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MissingInstanceHandlingStrategy.java index 92e30f1617..c431766c4c 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MissingInstanceHandlingStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MissingInstanceHandlingStrategy.java @@ -9,6 +9,8 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig; import org.opendaylight.controller.config.util.ConfigTransactionClient; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper; import org.slf4j.Logger; @@ -24,13 +26,16 @@ public class MissingInstanceHandlingStrategy extends AbstractEditConfigStrategy @Override void handleMissingInstance(Map configuration, ConfigTransactionClient ta, - String module, String instance, ServiceRegistryWrapper services) { + String module, String instance, ServiceRegistryWrapper services) throws NetconfConfigHandlingException { ObjectName on = null; try { on = ta.createModule(module, instance); logger.trace("New instance for {} {} created under name {}", module, instance, on); } catch (InstanceAlreadyExistsException e1) { - throw new IllegalStateException("Unable to create instance for " + module + " : " + instance); + throw new NetconfConfigHandlingException(String.format("Unable to create instance for %s : %s.", module, instance), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.operation_failed, + NetconfDocumentedException.ErrorSeverity.error); } } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/ReplaceEditConfigStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/ReplaceEditConfigStrategy.java index 4976244eae..b61fcbadc0 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/ReplaceEditConfigStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/ReplaceEditConfigStrategy.java @@ -12,6 +12,8 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; import org.opendaylight.controller.config.util.ConfigTransactionClient; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper; import org.slf4j.Logger; @@ -39,10 +41,14 @@ public class ReplaceEditConfigStrategy extends AbstractEditConfigStrategy { @Override void handleMissingInstance(Map configuration, ConfigTransactionClient ta, - String module, String instance, ServiceRegistryWrapper services) { - throw new IllegalStateException( - "Unable to handle missing instance, no missing instances should appear at this point, missing: " - + module + ":" + instance); + String module, String instance, ServiceRegistryWrapper services) throws NetconfConfigHandlingException { + throw new NetconfConfigHandlingException( + String.format("Unable to handle missing instance, no missing instances should appear at this point, missing: %s : %s ", + module, + instance), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.operation_failed, + NetconfDocumentedException.ErrorSeverity.error); } private void addRefNames(ServiceRegistryWrapper services, Multimap providedServices, ConfigTransactionClient ta, ObjectName on) throws InstanceNotFoundException { @@ -60,11 +66,14 @@ public class ReplaceEditConfigStrategy extends AbstractEditConfigStrategy { } @Override - void executeStrategy(Map configuration, ConfigTransactionClient ta, ObjectName on, ServiceRegistryWrapper services) { + void executeStrategy(Map configuration, ConfigTransactionClient ta, ObjectName on, ServiceRegistryWrapper services) throws NetconfConfigHandlingException { try { addRefNames(services, providedServices, ta, on); } catch (InstanceNotFoundException e) { - throw new IllegalStateException("Unable to save default ref name for instance " + on, e); + throw new NetconfConfigHandlingException(String.format("Unable to save default ref name for instance %s. Instance not found. ",on), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.operation_failed, + NetconfDocumentedException.ErrorSeverity.error); } for (Entry configAttributeEntry : configuration.entrySet()) { diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java index f7fc029fcc..dd0e53b1bb 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java @@ -8,22 +8,12 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.get; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.management.ObjectName; - +import com.google.common.collect.Maps; import org.opendaylight.controller.config.util.ConfigRegistryClient; import org.opendaylight.controller.config.util.ConfigTransactionClient; -import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot; import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; -import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity; -import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag; -import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfig; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleConfig; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper; @@ -33,7 +23,11 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.runtim import org.opendaylight.controller.netconf.confignetconfconnector.operations.AbstractConfigNetconfOperation; import org.opendaylight.controller.netconf.confignetconfconnector.operations.Datastore; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot; import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider; +import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException; +import org.opendaylight.controller.netconf.util.exception.UnexpectedElementException; +import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; import org.slf4j.Logger; @@ -41,7 +35,10 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import com.google.common.collect.Maps; +import javax.management.ObjectName; +import java.util.List; +import java.util.Map; +import java.util.Set; public class Get extends AbstractConfigNetconfOperation { @@ -106,7 +103,7 @@ public class Get extends AbstractConfigNetconfOperation { return jmxToYangNamesForChildRbe; } - private static void checkXml(XmlElement xml) { + private static void checkXml(XmlElement xml) throws UnexpectedElementException, UnexpectedNamespaceException, MissingNameSpaceException { xml.checkName(XmlNetconfConstants.GET); xml.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); @@ -122,21 +119,7 @@ public class Get extends AbstractConfigNetconfOperation { @Override protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException { - try { - checkXml(xml); - } catch (final IllegalArgumentException e) { - logger.warn("Error parsing xml", e); - final Map errorInfo = new HashMap<>(); - errorInfo.put(ErrorTag.bad_attribute.name(), e.getMessage()); - throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.rpc, ErrorTag.bad_attribute, - ErrorSeverity.error, errorInfo); - } catch (final UnsupportedOperationException e) { - logger.warn("Unsupported", e); - final Map errorInfo = new HashMap<>(); - errorInfo.put(ErrorTag.operation_not_supported.name(), "Unsupported option for 'get'"); - throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.application, - ErrorTag.operation_not_supported, ErrorSeverity.error, errorInfo); - } + checkXml(xml); final Set runtimeBeans = configRegistryClient.lookupRuntimeBeans(); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java index 05bba56611..11d3e32edf 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java @@ -8,18 +8,10 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.getconfig; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import javax.management.ObjectName; - +import com.google.common.base.Optional; import org.opendaylight.controller.config.util.ConfigRegistryClient; import org.opendaylight.controller.config.util.ConfigTransactionClient; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; -import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity; -import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag; -import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper; import org.opendaylight.controller.netconf.confignetconfconnector.operations.AbstractConfigNetconfOperation; @@ -27,6 +19,9 @@ import org.opendaylight.controller.netconf.confignetconfconnector.operations.Dat import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig; import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot; import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider; +import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException; +import org.opendaylight.controller.netconf.util.exception.UnexpectedElementException; +import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; import org.opendaylight.controller.netconf.util.xml.XmlUtil; @@ -35,7 +30,8 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import com.google.common.base.Optional; +import javax.management.ObjectName; +import java.util.Set; public class GetConfig extends AbstractConfigNetconfOperation { @@ -57,7 +53,8 @@ public class GetConfig extends AbstractConfigNetconfOperation { this.transactionProvider = transactionProvider; } - public static Datastore fromXml(XmlElement xml) { + public static Datastore fromXml(XmlElement xml) throws UnexpectedNamespaceException, UnexpectedElementException, MissingNameSpaceException, NetconfDocumentedException { + xml.checkName(GET_CONFIG); xml.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); @@ -106,27 +103,7 @@ public class GetConfig extends AbstractConfigNetconfOperation { @Override public Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException { Datastore source; - try { - source = fromXml(xml); - } catch (final IllegalArgumentException e) { - logger.warn("Rpc error: {}", ErrorTag.bad_attribute, e); - final Map errorInfo = new HashMap<>(); - errorInfo.put(ErrorTag.bad_attribute.name(), e.getMessage()); - throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.rpc, ErrorTag.bad_attribute, - ErrorSeverity.error, errorInfo); - } catch (final IllegalStateException e) { - logger.warn("Rpc error: {}", ErrorTag.missing_attribute, e); - final Map errorInfo = new HashMap<>(); - errorInfo.put(ErrorTag.missing_attribute.name(), "Missing datasource attribute value"); - throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.rpc, ErrorTag.missing_attribute, - ErrorSeverity.error, errorInfo); - } catch (final UnsupportedOperationException e) { - logger.warn("Unsupported", e); - final Map errorInfo = new HashMap<>(); - errorInfo.put(ErrorTag.operation_not_supported.name(), "Unsupported option for get"); - throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.application, - ErrorTag.operation_not_supported, ErrorSeverity.error, errorInfo); - } + source = fromXml(xml); return getResponseInternal(document, configRegistryClient, source); } } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java index 8accbd591f..5a30fc8352 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java @@ -8,11 +8,9 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.runtimerpc; -import java.util.Map; - -import javax.management.ObjectName; -import javax.management.openmbean.OpenType; - +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.Maps; import org.opendaylight.controller.config.util.ConfigRegistryClient; import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry; @@ -31,6 +29,7 @@ import org.opendaylight.controller.netconf.confignetconfconnector.operations.Abs import org.opendaylight.controller.netconf.confignetconfconnector.operations.Commit; import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot; import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; +import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; import org.opendaylight.controller.netconf.util.xml.XmlUtil; @@ -39,9 +38,9 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.collect.Maps; +import javax.management.ObjectName; +import javax.management.openmbean.OpenType; +import java.util.Map; public class RuntimeRpc extends AbstractConfigNetconfOperation { @@ -56,7 +55,7 @@ public class RuntimeRpc extends AbstractConfigNetconfOperation { this.yangStoreSnapshot = yangStoreSnapshot; } - private Element toXml(Document doc, Object result, AttributeIfc returnType, String namespace, String elementName) { + private Element toXml(Document doc, Object result, AttributeIfc returnType, String namespace, String elementName) throws NetconfDocumentedException { AttributeMappingStrategy> mappingStrategy = new ObjectMapper(null).prepareStrategy(returnType); Optional mappedAttributeOpt = mappingStrategy.mapAttribute(result); Preconditions.checkState(mappedAttributeOpt.isPresent(), "Unable to map return value %s as %s", result, returnType.getOpenType()); @@ -94,7 +93,13 @@ public class RuntimeRpc extends AbstractConfigNetconfOperation { } public NetconfOperationExecution fromXml(final XmlElement xml) throws NetconfDocumentedException { - final String namespace = xml.getNamespace(); + final String namespace; + try { + namespace = xml.getNamespace(); + } catch (MissingNameSpaceException e) { + logger.trace("Can't get namespace from xml element due to {}",e); + throw NetconfDocumentedException.wrap(e); + } final XmlElement contextInstanceElement = xml.getOnlyChildElement(CONTEXT_INSTANCE); final String operationName = xml.getName(); @@ -117,12 +122,19 @@ public class RuntimeRpc extends AbstractConfigNetconfOperation { } @Override - public HandlingPriority canHandle(Document message) { - XmlElement requestElement = getRequestElementWithCheck(message); + public HandlingPriority canHandle(Document message) throws NetconfDocumentedException { + XmlElement requestElement = null; + requestElement = getRequestElementWithCheck(message); XmlElement operationElement = requestElement.getOnlyChildElement(); final String netconfOperationName = operationElement.getName(); - final String netconfOperationNamespace = operationElement.getNamespace(); + final String netconfOperationNamespace; + try { + netconfOperationNamespace = operationElement.getNamespace(); + } catch (MissingNameSpaceException e) { + logger.debug("Cannot retrieve netconf operation namespace from message due to {}", e); + return HandlingPriority.CANNOT_HANDLE; + } final Optional contextInstanceElement = operationElement .getOnlyChildElementOptionally(CONTEXT_INSTANCE); @@ -165,10 +177,7 @@ public class RuntimeRpc extends AbstractConfigNetconfOperation { @Override protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException { - - // TODO exception handling // TODO check for namespaces and unknown elements - final NetconfOperationExecution execution = fromXml(xml); logger.debug("Invoking operation {} on {} with arguments {}", execution.operationName, execution.on, diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/transactions/TransactionProvider.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/transactions/TransactionProvider.java index d7cbf6680d..756a38ed94 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/transactions/TransactionProvider.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/transactions/TransactionProvider.java @@ -15,6 +15,8 @@ import org.opendaylight.controller.config.api.ValidationException; import org.opendaylight.controller.config.api.jmx.CommitStatus; import org.opendaylight.controller.config.util.ConfigRegistryClient; import org.opendaylight.controller.config.util.ConfigTransactionClient; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.confignetconfconnector.exception.NoTransactionFoundException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -94,9 +96,14 @@ public class TransactionProvider implements AutoCloseable { /** * Commit and notification send must be atomic */ - public synchronized CommitStatus commitTransaction() throws ValidationException, ConflictingVersionException { + public synchronized CommitStatus commitTransaction() throws ValidationException, ConflictingVersionException, NoTransactionFoundException { + if (!getTransaction().isPresent()){ + throw new NoTransactionFoundException("No transaction found for session " + netconfSessionIdForReporting, + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.operation_failed, + NetconfDocumentedException.ErrorSeverity.error); + } final Optional maybeTaON = getTransaction(); - Preconditions.checkState(maybeTaON.isPresent(), "No transaction found for session " + netconfSessionIdForReporting); ObjectName taON = maybeTaON.get(); try { CommitStatus status = configRegistryClient.commitConfig(taON); diff --git a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java index cd38d3babe..f151949abc 100644 --- a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java +++ b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java @@ -8,39 +8,11 @@ package org.opendaylight.controller.netconf.confignetconfconnector; -import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElement; -import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElementWithText; -import static org.opendaylight.controller.netconf.util.xml.XmlUtil.readXmlToElement; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.management.InstanceAlreadyExistsException; -import javax.management.InstanceNotFoundException; -import javax.management.ObjectName; -import javax.xml.parsers.ParserConfigurationException; - +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import org.custommonkey.xmlunit.AbstractNodeTester; import org.custommonkey.xmlunit.NodeTest; import org.custommonkey.xmlunit.NodeTestException; @@ -74,7 +46,6 @@ import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleMX import org.opendaylight.controller.config.yang.test.impl.Peers; import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter; import org.opendaylight.controller.netconf.confignetconfconnector.operations.Commit; import org.opendaylight.controller.netconf.confignetconfconnector.operations.DiscardChanges; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig; @@ -85,6 +56,7 @@ import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStore import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot; import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider; import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession; +import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter; import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshotImpl; import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; @@ -111,11 +83,37 @@ import org.w3c.dom.Text; import org.w3c.dom.traversal.DocumentTraversal; import org.xml.sax.SAXException; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; +import javax.management.InstanceAlreadyExistsException; +import javax.management.InstanceNotFoundException; +import javax.management.ObjectName; +import javax.xml.parsers.ParserConfigurationException; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElement; +import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElementWithText; +import static org.opendaylight.controller.netconf.util.xml.XmlUtil.readXmlToElement; public class NetconfMappingTest extends AbstractConfigTest { @@ -567,7 +565,7 @@ public class NetconfMappingTest extends AbstractConfigTest { assertThat(string, JUnitMatchers.containsString(substring)); } - private void checkEnum(final Document response) { + private void checkEnum(final Document response) throws NetconfDocumentedException { XmlElement modulesElement = XmlElement.fromDomElement(response.getDocumentElement()).getOnlyChildElement("data") .getOnlyChildElement("modules"); @@ -591,7 +589,7 @@ public class NetconfMappingTest extends AbstractConfigTest { assertEquals(2, testingDepsSize); } - private void checkTypeConfigAttribute(Document response) { + private void checkTypeConfigAttribute(Document response) throws NetconfDocumentedException { XmlElement modulesElement = XmlElement.fromDomElement(response.getDocumentElement()).getOnlyChildElement("data") .getOnlyChildElement("modules"); diff --git a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigTest.java b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigTest.java index ae5a9930d2..4d9935eafb 100644 --- a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigTest.java +++ b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigTest.java @@ -20,7 +20,6 @@ import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry; import org.opendaylight.controller.config.api.ValidationException; import org.opendaylight.controller.config.util.ConfigRegistryClient; import org.opendaylight.controller.config.util.ConfigTransactionClient; -import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfigElementResolved; @@ -30,6 +29,7 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services; import org.opendaylight.controller.netconf.confignetconfconnector.operations.ValidateTest; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfigXmlParser.EditConfigExecution; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot; import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider; import org.opendaylight.controller.netconf.util.xml.XmlUtil; @@ -104,7 +104,7 @@ public class EditConfigTest { any(ConfigTransactionClient.class), any(ServiceRegistryWrapper.class)); } - private EditConfigExecution mockExecution(EditConfigStrategy editStrat) { + private EditConfigExecution mockExecution(EditConfigStrategy editStrat) throws NetconfDocumentedException { EditConfigExecution mock = mock(EditConfigExecution.class); doReturn(getMapping(editStrat)).when(mock).getResolvedXmlElements(any(ConfigTransactionClient.class)); doReturn(getMappingDefinition(editStrat)).when(mock).getModulesDefinition(any(ConfigTransactionClient.class)); diff --git a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusher.java b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusher.java index ed5a3a97a4..44e90270e7 100644 --- a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusher.java +++ b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusher.java @@ -59,7 +59,7 @@ public class ConfigPusher { this.conflictingVersionTimeoutMillis = conflictingVersionTimeoutMillis; } - public synchronized LinkedHashMap pushConfigs(List configs) { + public synchronized LinkedHashMap pushConfigs(List configs) throws NetconfDocumentedException { logger.debug("Last config snapshots to be pushed to netconf: {}", configs); LinkedHashMap result = new LinkedHashMap<>(); // start pushing snapshots: @@ -78,7 +78,7 @@ public class ConfigPusher { * is caught, whole process is retried - new service instance need to be obtained from the factory. Closes * {@link NetconfOperationService} after each use. */ - private synchronized EditAndCommitResponse pushConfigWithConflictingVersionRetries(ConfigSnapshotHolder configSnapshotHolder) { + private synchronized EditAndCommitResponse pushConfigWithConflictingVersionRetries(ConfigSnapshotHolder configSnapshotHolder) throws NetconfDocumentedException { ConflictingVersionException lastException; Stopwatch stopwatch = new Stopwatch().start(); do { @@ -139,7 +139,7 @@ public class ConfigPusher { } else { serviceCandidate.close(); logger.trace("Netconf server did not provide required capabilities for {} " + - "Expected but not found: {}, all expected {}, current {}", + "Expected but not found: {}, all expected {}, current {}", idForReporting, notFoundDiff, expectedCapabilities, serviceCandidate.getCapabilities() ); throw new NotEnoughCapabilitiesException("Not enough capabilities for " + idForReporting + ". Expected but not found: " + notFoundDiff); @@ -177,7 +177,7 @@ public class ConfigPusher { * @throws java.lang.RuntimeException if edit-config or commit fails otherwise */ private synchronized EditAndCommitResponse pushConfig(ConfigSnapshotHolder configSnapshotHolder, NetconfOperationService operationService) - throws ConflictingVersionException { + throws ConflictingVersionException, NetconfDocumentedException { Element xmlToBePersisted; try { @@ -209,7 +209,7 @@ public class ConfigPusher { return new EditAndCommitResponse(editResponseMessage, commitResponseMessage); } - private NetconfOperation findOperation(NetconfMessage request, NetconfOperationService operationService) { + private NetconfOperation findOperation(NetconfMessage request, NetconfOperationService operationService) throws NetconfDocumentedException { TreeMap allOperations = new TreeMap<>(); Set netconfOperations = operationService.getNetconfOperations(); if (netconfOperations.isEmpty()) { @@ -228,7 +228,7 @@ public class ConfigPusher { private Document sendRequestGetResponseCheckIsOK(NetconfMessage request, NetconfOperationService operationService, String operationNameForReporting, String configIdForReporting) - throws ConflictingVersionException { + throws ConflictingVersionException, NetconfDocumentedException { NetconfOperation operation = findOperation(request, operationService); Document response; @@ -245,7 +245,7 @@ public class ConfigPusher { } // load editConfig.xml template, populate /rpc/edit-config/config with parameter - private static NetconfMessage createEditConfigMessage(Element dataElement) { + private static NetconfMessage createEditConfigMessage(Element dataElement) throws NetconfDocumentedException { String editConfigResourcePath = "/netconfOp/editConfig.xml"; try (InputStream stream = ConfigPersisterNotificationHandler.class.getResourceAsStream(editConfigResourcePath)) { Preconditions.checkNotNull(stream, "Unable to load resource " + editConfigResourcePath); diff --git a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java index 0cc55719e1..1a261da323 100644 --- a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java +++ b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java @@ -10,6 +10,7 @@ package org.opendaylight.controller.netconf.persist.impl.osgi; import com.google.common.annotations.VisibleForTesting; import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler; @@ -151,7 +152,12 @@ public class ConfigPersisterActivator implements BundleActivator { final Thread pushingThread = new Thread(new Runnable() { @Override public void run() { - configPusher.pushConfigs(configs); + try { + configPusher.pushConfigs(configs); + } catch (NetconfDocumentedException e) { + logger.error("Error pushing configs {}",configs); + throw new IllegalStateException(e); + } logger.info("Configuration Persister initialization completed."); ConfigPersisterNotificationHandler jmxNotificationHandler = new ConfigPersisterNotificationHandler(platformMBeanServer, persisterAggregator); synchronized (ConfigPersisterActivator.this) { diff --git a/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfDocumentedException.java b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfDocumentedException.java index ceeca51def..57bd3dd620 100644 --- a/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfDocumentedException.java +++ b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfDocumentedException.java @@ -90,6 +90,12 @@ public class NetconfDocumentedException extends Exception { this.errorInfo = errorInfo; } + public static NetconfDocumentedException wrap(E exception) throws NetconfDocumentedException { + final Map errorInfo = new HashMap<>(); + errorInfo.put(ErrorTag.operation_failed.name(), "Exception thrown"); + throw new NetconfDocumentedException(exception.getMessage(), exception, ErrorType.application, ErrorTag.operation_failed, + ErrorSeverity.error, errorInfo); + } public static NetconfDocumentedException wrap(ValidationException e) throws NetconfDocumentedException { final Map errorInfo = new HashMap<>(); errorInfo.put(ErrorTag.operation_failed.name(), "Validation failed"); diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSessionNegotiator.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSessionNegotiator.java index 83f49b2635..8a40bee994 100644 --- a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSessionNegotiator.java +++ b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSessionNegotiator.java @@ -8,10 +8,15 @@ package org.opendaylight.controller.netconf.client; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpression; - +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.util.Timer; +import io.netty.util.concurrent.Promise; import org.opendaylight.controller.netconf.api.NetconfClientSessionPreferences; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.util.AbstractChannelInitializer; import org.opendaylight.controller.netconf.util.AbstractNetconfSessionNegotiator; @@ -26,13 +31,8 @@ import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.util.Timer; -import io.netty.util.concurrent.Promise; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; public class NetconfClientSessionNegotiator extends AbstractNetconfSessionNegotiator @@ -54,7 +54,7 @@ public class NetconfClientSessionNegotiator extends } @Override - protected void handleMessage(NetconfHelloMessage netconfMessage) { + protected void handleMessage(NetconfHelloMessage netconfMessage) throws NetconfDocumentedException { NetconfClientSession session = super.getSessionForHelloMessage(netconfMessage); if (shouldUseExi(netconfMessage.getDocument())){ @@ -109,7 +109,7 @@ public class NetconfClientSessionNegotiator extends } @Override - protected NetconfClientSession getSession(NetconfClientSessionListener sessionListener, Channel channel, NetconfHelloMessage message) { + protected NetconfClientSession getSession(NetconfClientSessionListener sessionListener, Channel channel, NetconfHelloMessage message) throws NetconfDocumentedException { return new NetconfClientSession(sessionListener, channel, extractSessionId(message.getDocument()), NetconfMessageUtil.extractCapabilitiesFromHello(message.getDocument())); } diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSessionNegotiatorFactory.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSessionNegotiatorFactory.java index 07e088e117..9e15b49a84 100644 --- a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSessionNegotiatorFactory.java +++ b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSessionNegotiatorFactory.java @@ -8,7 +8,14 @@ package org.opendaylight.controller.netconf.client; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.Sets; +import io.netty.channel.Channel; +import io.netty.util.Timer; +import io.netty.util.concurrent.Promise; import org.opendaylight.controller.netconf.api.NetconfClientSessionPreferences; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage; import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader; @@ -20,14 +27,8 @@ import org.opendaylight.protocol.framework.SessionNegotiatorFactory; import org.openexi.proc.common.AlignmentType; import org.openexi.proc.common.EXIOptions; import org.openexi.proc.common.EXIOptionsException; - -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.collect.Sets; - -import io.netty.channel.Channel; -import io.netty.util.Timer; -import io.netty.util.concurrent.Promise; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class NetconfClientSessionNegotiatorFactory implements SessionNegotiatorFactory { @@ -42,6 +43,7 @@ public class NetconfClientSessionNegotiatorFactory implements SessionNegotiatorF private final long connectionTimeoutMillis; private final Timer timer; private final EXIOptions options; + private static final Logger logger = LoggerFactory.getLogger(NetconfClientSessionNegotiatorFactory.class); public NetconfClientSessionNegotiatorFactory(Timer timer, Optional additionalHeader, @@ -64,7 +66,13 @@ public class NetconfClientSessionNegotiatorFactory implements SessionNegotiatorF Promise promise) { NetconfMessage startExiMessage = NetconfStartExiMessage.create(options, START_EXI_MESSAGE_ID); - NetconfHelloMessage helloMessage = NetconfHelloMessage.createClientHello(CLIENT_CAPABILITIES, additionalHeader); + NetconfHelloMessage helloMessage = null; + try { + helloMessage = NetconfHelloMessage.createClientHello(CLIENT_CAPABILITIES, additionalHeader); + } catch (NetconfDocumentedException e) { + logger.error("Unable to create client hello message with capabilities {} and additional handler {}",CLIENT_CAPABILITIES,additionalHeader); + throw new IllegalStateException(e); + } NetconfClientSessionPreferences proposal = new NetconfClientSessionPreferences(helloMessage,startExiMessage); return new NetconfClientSessionNegotiator(proposal, promise, channel, timer, diff --git a/opendaylight/netconf/netconf-impl/pom.xml b/opendaylight/netconf/netconf-impl/pom.xml index 9694a90c49..c62a85aae6 100644 --- a/opendaylight/netconf/netconf-impl/pom.xml +++ b/opendaylight/netconf/netconf-impl/pom.xml @@ -129,6 +129,7 @@ org.opendaylight.controller.netconf.util.mapping, org.opendaylight.controller.netconf.util.osgi, org.opendaylight.controller.netconf.util.xml, + org.opendaylight.controller.netconf.util.exception, org.opendaylight.controller.netconf.util.handler, org.opendaylight.protocol.framework, org.osgi.framework, diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiatorFactory.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiatorFactory.java index 9106b6ad85..9d95866061 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiatorFactory.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiatorFactory.java @@ -8,10 +8,11 @@ package org.opendaylight.controller.netconf.impl; -import static org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider.NetconfOperationProviderUtil.getNetconfSessionIdForReporting; - -import java.util.Set; - +import com.google.common.collect.Sets; +import io.netty.channel.Channel; +import io.netty.util.Timer; +import io.netty.util.concurrent.Promise; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfServerSessionPreferences; import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider; import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService; @@ -22,12 +23,12 @@ import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; import org.opendaylight.protocol.framework.SessionListenerFactory; import org.opendaylight.protocol.framework.SessionNegotiator; import org.opendaylight.protocol.framework.SessionNegotiatorFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import com.google.common.collect.Sets; +import java.util.Set; -import io.netty.channel.Channel; -import io.netty.util.Timer; -import io.netty.util.concurrent.Promise; +import static org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider.NetconfOperationProviderUtil.getNetconfSessionIdForReporting; public class NetconfServerSessionNegotiatorFactory implements SessionNegotiatorFactory { @@ -42,6 +43,7 @@ public class NetconfServerSessionNegotiatorFactory implements SessionNegotiatorF private final long connectionTimeoutMillis; private final DefaultCommitNotificationProducer commitNotificationProducer; private final SessionMonitoringService monitoringService; + private static final Logger logger = LoggerFactory.getLogger(NetconfServerSessionNegotiatorFactory.class); public NetconfServerSessionNegotiatorFactory(Timer timer, NetconfOperationProvider netconfOperationProvider, SessionIdProvider idProvider, long connectionTimeoutMillis, @@ -71,8 +73,14 @@ public class NetconfServerSessionNegotiatorFactory implements SessionNegotiatorF getNetconfSessionIdForReporting(sessionId)); CapabilityProvider capabilityProvider = new CapabilityProviderImpl(netconfOperationServiceSnapshot); - NetconfServerSessionPreferences proposal = new NetconfServerSessionPreferences( - createHelloMessage(sessionId, capabilityProvider), sessionId); + NetconfServerSessionPreferences proposal = null; + try { + proposal = new NetconfServerSessionPreferences( + createHelloMessage(sessionId, capabilityProvider), sessionId); + } catch (NetconfDocumentedException e) { + logger.error("Unable to create hello mesage for session {} with capability provider {}", sessionId,capabilityProvider); + throw new IllegalStateException(e); + } NetconfServerSessionListenerFactory sessionListenerFactory = new NetconfServerSessionListenerFactory( commitNotificationProducer, monitoringService, @@ -82,7 +90,7 @@ public class NetconfServerSessionNegotiatorFactory implements SessionNegotiatorF sessionListenerFactory.getSessionListener(), connectionTimeoutMillis); } - private NetconfHelloMessage createHelloMessage(long sessionId, CapabilityProvider capabilityProvider) { + private NetconfHelloMessage createHelloMessage(long sessionId, CapabilityProvider capabilityProvider) throws NetconfDocumentedException { return NetconfHelloMessage.createServerHello(Sets.union(capabilityProvider.getCapabilities(), DEFAULT_CAPABILITIES), sessionId); } diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java index 1a9f5d7393..d6940a1a45 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java @@ -8,9 +8,7 @@ package org.opendaylight.controller.netconf.impl.mapping.operations; -import java.io.InputStream; -import java.util.Map; - +import com.google.common.base.Preconditions; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter; import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; @@ -26,8 +24,7 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import com.google.common.base.Preconditions; -import com.google.common.collect.Maps; +import java.io.InputStream; public class DefaultCommit extends AbstractNetconfOperation { @@ -100,8 +97,14 @@ public class DefaultCommit extends AbstractNetconfOperation { } private boolean isCommitWithoutNotification(Document message) { - XmlElement xmlElement = XmlElement.fromDomElementWithExpected(message.getDocumentElement(), - XmlNetconfConstants.RPC_KEY, XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); + XmlElement xmlElement = null; + try { + xmlElement = XmlElement.fromDomElementWithExpected(message.getDocumentElement(), + XmlNetconfConstants.RPC_KEY, XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); + } catch (NetconfDocumentedException e) { + logger.trace("Commit operation is not valid due to {}",e); + return false; + } String attr = xmlElement.getAttribute(NOTIFY_ATTR); @@ -120,20 +123,9 @@ public class DefaultCommit extends AbstractNetconfOperation { getConfigMessage, null); XmlElement dataElement; - try { - XmlElement xmlElement = XmlElement.fromDomElementWithExpected(responseDocument.getDocumentElement(), - XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); - dataElement = xmlElement.getOnlyChildElement(XmlNetconfConstants.DATA_KEY); - } catch (IllegalArgumentException e) { - final String msg = "Unexpected response from get-config operation"; - logger.warn(msg, e); - Map info = Maps.newHashMap(); - info.put(NetconfDocumentedException.ErrorTag.operation_failed.toString(), e.getMessage()); - throw new NetconfDocumentedException(msg, e, NetconfDocumentedException.ErrorType.application, - NetconfDocumentedException.ErrorTag.operation_failed, - NetconfDocumentedException.ErrorSeverity.error, info); - } - + XmlElement xmlElement = XmlElement.fromDomElementWithExpected(responseDocument.getDocumentElement(), + XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); + dataElement = xmlElement.getOnlyChildElement(XmlNetconfConstants.DATA_KEY); return dataElement.getDomElement(); } diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultGetSchema.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultGetSchema.java index f50dd3e706..beceb8d008 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultGetSchema.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultGetSchema.java @@ -8,11 +8,11 @@ package org.opendaylight.controller.netconf.impl.mapping.operations; -import java.util.HashMap; -import java.util.Map; - +import com.google.common.base.Optional; +import com.google.common.collect.Maps; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider; +import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException; import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; @@ -22,8 +22,7 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import com.google.common.base.Optional; -import com.google.common.collect.Maps; +import java.util.Map; public final class DefaultGetSchema extends AbstractLastNetconfOperation { public static final String GET_SCHEMA = "get-schema"; @@ -52,23 +51,7 @@ public final class DefaultGetSchema extends AbstractLastNetconfOperation { protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException { GetSchemaEntry entry; - try { - entry = new GetSchemaEntry(xml); - } catch (final IllegalArgumentException e) { - logger.warn("Error parsing xml", e); - final Map errorInfo = new HashMap<>(); - errorInfo.put(NetconfDocumentedException.ErrorTag.bad_attribute.name(), e.getMessage()); - throw new NetconfDocumentedException(e.getMessage(), e, NetconfDocumentedException.ErrorType.rpc, - NetconfDocumentedException.ErrorTag.bad_attribute, NetconfDocumentedException.ErrorSeverity.error, - errorInfo); - } catch (final IllegalStateException e) { - logger.warn("Error parsing xml", e); - final Map errorInfo = new HashMap<>(); - errorInfo.put(NetconfDocumentedException.ErrorTag.bad_attribute.name(), e.getMessage()); - throw new NetconfDocumentedException(e.getMessage(), e, NetconfDocumentedException.ErrorType.rpc, - NetconfDocumentedException.ErrorTag.bad_attribute, NetconfDocumentedException.ErrorSeverity.error, - errorInfo); - } + entry = new GetSchemaEntry(xml); String schema; try { @@ -94,11 +77,17 @@ public final class DefaultGetSchema extends AbstractLastNetconfOperation { private final String identifier; private final Optional version; - GetSchemaEntry(XmlElement getSchemaElement) { + GetSchemaEntry(XmlElement getSchemaElement) throws NetconfDocumentedException { getSchemaElement.checkName(GET_SCHEMA); getSchemaElement.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_YANG_IETF_NETCONF_MONITORING); - XmlElement identifierElement = getSchemaElement.getOnlyChildElementWithSameNamespace(IDENTIFIER); + XmlElement identifierElement = null; + try { + identifierElement = getSchemaElement.getOnlyChildElementWithSameNamespace(IDENTIFIER); + } catch (MissingNameSpaceException e) { + logger.trace("Can't get identifier element as only child element with same namespace due to {}",e); + throw NetconfDocumentedException.wrap(e); + } identifier = identifierElement.getTextContent(); Optional versionElement = getSchemaElement .getOnlyChildElementWithSameNamespaceOptionally(VERSION); diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java index bb4c76a4b8..c2ab36f2c6 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java @@ -153,7 +153,7 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter { } private NetconfOperationExecution getNetconfOperationWithHighestPriority( - Document message, NetconfServerSession session) { + Document message, NetconfServerSession session) throws NetconfDocumentedException { TreeMap sortedByPriority = getSortedNetconfOperationsWithCanHandle( message, session); @@ -166,7 +166,7 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter { } private TreeMap getSortedNetconfOperationsWithCanHandle(Document message, - NetconfServerSession session) { + NetconfServerSession session) throws NetconfDocumentedException { TreeMap sortedPriority = Maps.newTreeMap(); for (NetconfOperation netconfOperation : allNetconfOperations) { @@ -185,6 +185,21 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter { return sortedPriority; } + public static final NetconfOperationChainedExecution EXECUTION_TERMINATION_POINT = new NetconfOperationChainedExecution() { + @Override + public boolean isExecutionTermination() { + return true; + } + + @Override + public Document execute(Document requestMessage) throws NetconfDocumentedException { + throw new NetconfDocumentedException("This execution represents the termination point in operation execution and cannot be executed itself", + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.operation_failed, + NetconfDocumentedException.ErrorSeverity.error); + } + }; + private static class NetconfOperationExecution implements NetconfOperationChainedExecution { private final NetconfOperation netconfOperation; private NetconfOperationChainedExecution subsequentExecution; diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java index d169858d35..634a18f852 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java @@ -22,16 +22,17 @@ import org.junit.Test; import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver; import org.opendaylight.controller.config.spi.ModuleFactory; import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; -import org.opendaylight.controller.netconf.client.test.TestingNetconfClient; -import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException; import org.opendaylight.controller.config.yang.test.impl.DepTestImplModuleFactory; import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory; import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleMXBean; import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory; import org.opendaylight.controller.netconf.StubUserManager; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.client.NetconfClientDispatcher; +import org.opendaylight.controller.netconf.client.test.TestingNetconfClient; import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException; import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher; import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl; @@ -321,17 +322,17 @@ public class NetconfITTest extends AbstractNetconfConfigTest { } } - private void assertIsOK(final Document rpcReply) { + private void assertIsOK(final Document rpcReply) throws NetconfDocumentedException { assertEquals("rpc-reply", rpcReply.getDocumentElement().getLocalName()); assertEquals("ok", XmlElement.fromDomDocument(rpcReply).getOnlyChildElement().getName()); } - private Document assertGetConfigWorks(final TestingNetconfClient netconfClient) throws InterruptedException, ExecutionException, TimeoutException { + private Document assertGetConfigWorks(final TestingNetconfClient netconfClient) throws InterruptedException, ExecutionException, TimeoutException, NetconfDocumentedException { return assertGetConfigWorks(netconfClient, this.getConfig); } private Document assertGetConfigWorks(final TestingNetconfClient netconfClient, final NetconfMessage getConfigMessage) - throws InterruptedException, ExecutionException, TimeoutException { + throws InterruptedException, ExecutionException, TimeoutException, NetconfDocumentedException { final NetconfMessage rpcReply = netconfClient.sendMessage(getConfigMessage); assertNotNull(rpcReply); assertEquals("data", XmlElement.fromDomDocument(rpcReply.getDocument()).getOnlyChildElement().getName()); diff --git a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperation.java b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperation.java index b70f8dbd39..c7298cbf1e 100644 --- a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperation.java +++ b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperation.java @@ -33,7 +33,7 @@ public interface NetconfOperation { * @param requestMessage * @return */ - HandlingPriority canHandle(Document requestMessage); + HandlingPriority canHandle(Document message) throws NetconfDocumentedException; /** * Execute current netconf operation and trigger execution of subsequent diff --git a/opendaylight/netconf/netconf-monitoring/pom.xml b/opendaylight/netconf/netconf-monitoring/pom.xml index 6730ccbb54..03193b8492 100644 --- a/opendaylight/netconf/netconf-monitoring/pom.xml +++ b/opendaylight/netconf/netconf-monitoring/pom.xml @@ -58,6 +58,7 @@ org.opendaylight.controller.netconf.api, org.opendaylight.controller.netconf.mapping.api, org.opendaylight.controller.netconf.util.mapping, + org.opendaylight.controller.netconf.util.exception, org.osgi.framework, org.slf4j, org.w3c.dom, diff --git a/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/Get.java b/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/Get.java index 08da36148f..6449c3e05f 100644 --- a/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/Get.java +++ b/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/Get.java @@ -7,8 +7,8 @@ */ package org.opendaylight.controller.netconf.monitoring; -import java.util.Map; - +import com.google.common.base.Preconditions; +import com.google.common.collect.Maps; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; @@ -24,8 +24,7 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import com.google.common.base.Preconditions; -import com.google.common.collect.Maps; +import java.util.Map; public class Get extends AbstractNetconfOperation { @@ -37,10 +36,11 @@ public class Get extends AbstractNetconfOperation { this.netconfMonitor = netconfMonitor; } - private Element getPlaceholder(Document innerResult) { + private Element getPlaceholder(Document innerResult) throws NetconfDocumentedException { try { - XmlElement rootElement = XmlElement.fromDomElementWithExpected(innerResult.getDocumentElement(), - XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); + XmlElement rootElement = null; + rootElement = XmlElement.fromDomElementWithExpected(innerResult.getDocumentElement(), + XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.RFC4741_TARGET_NAMESPACE); return rootElement.getOnlyChildElement(XmlNetconfConstants.DATA_KEY).getDomElement(); } catch (RuntimeException e) { throw new IllegalArgumentException(String.format( diff --git a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/NetconfSSHServer.java b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/NetconfSSHServer.java index 45807a8333..c2d0679155 100644 --- a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/NetconfSSHServer.java +++ b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/NetconfSSHServer.java @@ -7,17 +7,18 @@ */ package org.opendaylight.controller.netconf.ssh; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.util.concurrent.atomic.AtomicLong; -import javax.annotation.concurrent.ThreadSafe; import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider; import org.opendaylight.controller.netconf.ssh.threads.SocketThread; import org.opendaylight.controller.usermanager.IUserManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.concurrent.ThreadSafe; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.util.concurrent.atomic.AtomicLong; + @ThreadSafe public class NetconfSSHServer implements Runnable { @@ -69,7 +70,7 @@ public class NetconfSSHServer implements Runnable { try { SocketThread.start(ss.accept(), clientAddress, sesssionId.incrementAndGet(),authProvider); } catch (IOException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + logger.error("Exception occurred during socket thread initialization {}",e); } } } diff --git a/opendaylight/netconf/netconf-util/pom.xml b/opendaylight/netconf/netconf-util/pom.xml index 25db5f3f42..65d2954afd 100644 --- a/opendaylight/netconf/netconf-util/pom.xml +++ b/opendaylight/netconf/netconf-util/pom.xml @@ -77,7 +77,8 @@ org.opendaylight.controller.netconf.util.mapping, org.opendaylight.controller.netconf.util.messages, org.opendaylight.controller.netconf.util.handler, - org.opendaylight.controller.netconf.util.handler.*, + org.opendaylight.controller.netconf.util.handler.*, + org.opendaylight.controller.netconf.util.exception, com.google.common.base, com.google.common.collect, ch.ethz.ssh2, diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractNetconfSessionNegotiator.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractNetconfSessionNegotiator.java index 724b45bc08..5521e28818 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractNetconfSessionNegotiator.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractNetconfSessionNegotiator.java @@ -21,6 +21,7 @@ import io.netty.util.TimerTask; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; import io.netty.util.concurrent.Promise; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.api.NetconfSessionListener; import org.opendaylight.controller.netconf.api.NetconfSessionPreferences; @@ -133,12 +134,12 @@ extends AbstractSessionNegotiator { } @Override - protected void handleMessage(NetconfHelloMessage netconfMessage) { - S session = getSessionForHelloMessage(netconfMessage); + protected void handleMessage(NetconfHelloMessage netconfMessage) throws NetconfDocumentedException { + S session = getSessionForHelloMessage(netconfMessage) ; negotiationSuccessful(session); } - protected final S getSessionForHelloMessage(NetconfHelloMessage netconfMessage) { + protected final S getSessionForHelloMessage(NetconfHelloMessage netconfMessage) throws NetconfDocumentedException { Preconditions.checkNotNull(netconfMessage, "netconfMessage"); final Document doc = netconfMessage.getDocument(); @@ -180,7 +181,7 @@ extends AbstractSessionNegotiator { return channel.pipeline().replace(handlerKey, handlerKey, decoder); } - protected abstract S getSession(L sessionListener, Channel channel, NetconfHelloMessage message); + protected abstract S getSession(L sessionListener, Channel channel, NetconfHelloMessage message) throws NetconfDocumentedException; protected synchronized void changeState(final State newState) { logger.debug("Changing state from : {} to : {}", state, newState); diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/NetconfUtil.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/NetconfUtil.java index 29f40ce624..9443f93f92 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/NetconfUtil.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/NetconfUtil.java @@ -8,6 +8,7 @@ package org.opendaylight.controller.netconf.util; import com.google.common.base.Preconditions; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; @@ -52,11 +53,7 @@ public final class NetconfUtil { return (doc == null) ? null : new NetconfMessage(doc); } - public static Document checkIsMessageOk(NetconfMessage responseMessage) { - return checkIsMessageOk(responseMessage.getDocument()); - } - - public static Document checkIsMessageOk(Document response) { + public static Document checkIsMessageOk(Document response) throws NetconfDocumentedException { XmlElement element = XmlElement.fromDomDocument(response); Preconditions.checkState(element.getName().equals(XmlNetconfConstants.RPC_REPLY_KEY)); element = element.getOnlyChildElement(); diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/MissingNameSpaceException.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/MissingNameSpaceException.java new file mode 100644 index 0000000000..0a3e0b3ec3 --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/MissingNameSpaceException.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2013 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.controller.netconf.util.exception; + +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; + +import java.util.Collections; +import java.util.Map; + +public class MissingNameSpaceException extends NetconfDocumentedException { + + public MissingNameSpaceException(final String message, final ErrorType errorType, final ErrorTag errorTag, + final ErrorSeverity errorSeverity) { + this(message, errorType, errorTag, errorSeverity, Collections. emptyMap()); + } + + public MissingNameSpaceException(final String message, final ErrorType errorType, final ErrorTag errorTag, + final ErrorSeverity errorSeverity, final Map errorInfo){ + super(message,errorType,errorTag,errorSeverity,errorInfo); + } +} diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/UnexpectedElementException.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/UnexpectedElementException.java new file mode 100644 index 0000000000..b470ce13a8 --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/UnexpectedElementException.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2013 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.controller.netconf.util.exception; + +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; + +import java.util.Collections; +import java.util.Map; + +public class UnexpectedElementException extends NetconfDocumentedException { + + public UnexpectedElementException(final String message, final ErrorType errorType, final ErrorTag errorTag, + final ErrorSeverity errorSeverity) { + this(message, errorType, errorTag, errorSeverity, Collections. emptyMap()); + } + + public UnexpectedElementException(final String message, final ErrorType errorType, final ErrorTag errorTag, + final ErrorSeverity errorSeverity, final Map errorInfo){ + super(message,errorType,errorTag,errorSeverity,errorInfo); + } +} diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/UnexpectedNamespaceException.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/UnexpectedNamespaceException.java new file mode 100644 index 0000000000..50d7670780 --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/UnexpectedNamespaceException.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2013 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.controller.netconf.util.exception; + +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; + +import java.util.Collections; +import java.util.Map; + +public class UnexpectedNamespaceException extends NetconfDocumentedException { + + public UnexpectedNamespaceException(final String message, final ErrorType errorType, final ErrorTag errorTag, + final ErrorSeverity errorSeverity) { + this(message, errorType, errorTag, errorSeverity, Collections. emptyMap()); + } + + public UnexpectedNamespaceException(final String message, final ErrorType errorType, final ErrorTag errorTag, + final ErrorSeverity errorSeverity, final Map errorInfo){ + super(message,errorType,errorTag,errorSeverity,errorInfo); + } +} diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractLastNetconfOperation.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractLastNetconfOperation.java index d6d57c50ac..c40bf3909a 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractLastNetconfOperation.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractLastNetconfOperation.java @@ -14,8 +14,6 @@ import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.w3c.dom.Document; import org.w3c.dom.Element; -import com.google.common.base.Preconditions; - public abstract class AbstractLastNetconfOperation extends AbstractNetconfOperation { protected AbstractLastNetconfOperation(String netconfSessionIdForReporting) { @@ -25,8 +23,12 @@ public abstract class AbstractLastNetconfOperation extends AbstractNetconfOperat @Override protected Element handle(Document document, XmlElement operationElement, NetconfOperationChainedExecution subsequentOperation) throws NetconfDocumentedException { - Preconditions.checkArgument(subsequentOperation.isExecutionTermination(), - "No netconf operation expected to be subsequent to %s, but is %s", this, subsequentOperation); + if (!subsequentOperation.isExecutionTermination()){ + throw new NetconfDocumentedException(String.format("No netconf operation expected to be subsequent to %s, but is %s", this, subsequentOperation), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.malformed_message, + NetconfDocumentedException.ErrorSeverity.error); + } return handleWithNoSubsequentOperations(document, operationElement); } diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperation.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperation.java index b7bbd3c6a7..65ca1b7c4b 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperation.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperation.java @@ -17,6 +17,8 @@ import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedEx import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; import org.opendaylight.controller.netconf.util.xml.XmlUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -26,6 +28,7 @@ import com.google.common.base.Optional; public abstract class AbstractNetconfOperation implements NetconfOperation { private final String netconfSessionIdForReporting; + private static final Logger logger = LoggerFactory.getLogger(AbstractNetconfOperation.class); protected AbstractNetconfOperation(String netconfSessionIdForReporting) { this.netconfSessionIdForReporting = netconfSessionIdForReporting; @@ -36,16 +39,18 @@ public abstract class AbstractNetconfOperation implements NetconfOperation { } @Override - public HandlingPriority canHandle(Document message) { - OperationNameAndNamespace operationNameAndNamespace = new OperationNameAndNamespace(message); + public HandlingPriority canHandle(Document message) throws NetconfDocumentedException { + OperationNameAndNamespace operationNameAndNamespace = null; + operationNameAndNamespace = new OperationNameAndNamespace(message); return canHandle(operationNameAndNamespace.getOperationName(), operationNameAndNamespace.getNamespace()); } public static final class OperationNameAndNamespace { private final String operationName, namespace; - public OperationNameAndNamespace(Document message) { - XmlElement requestElement = getRequestElementWithCheck(message); + public OperationNameAndNamespace(Document message) throws NetconfDocumentedException { + XmlElement requestElement = null; + requestElement = getRequestElementWithCheck(message); XmlElement operationElement = requestElement.getOnlyChildElement(); operationName = operationElement.getName(); @@ -61,7 +66,7 @@ public abstract class AbstractNetconfOperation implements NetconfOperation { } } - protected static XmlElement getRequestElementWithCheck(Document message) { + protected static XmlElement getRequestElementWithCheck(Document message) throws NetconfDocumentedException { return XmlElement.fromDomElementWithExpected(message.getDocumentElement(), XmlNetconfConstants.RPC_KEY, XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); } diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessage.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessage.java index e3eb450704..3fd25e814d 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessage.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessage.java @@ -8,8 +8,9 @@ package org.opendaylight.controller.netconf.util.messages; -import java.util.Set; - +import com.google.common.base.Optional; +import com.google.common.collect.Sets; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; @@ -17,8 +18,7 @@ import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.w3c.dom.Document; import org.w3c.dom.Element; -import com.google.common.base.Optional; -import com.google.common.collect.Sets; +import java.util.Set; /** * NetconfMessage that can carry additional header with session metadata. See {@link org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader} @@ -29,13 +29,13 @@ public final class NetconfHelloMessage extends NetconfMessage { private final NetconfHelloMessageAdditionalHeader additionalHeader; - public NetconfHelloMessage(Document doc, NetconfHelloMessageAdditionalHeader additionalHeader) { + public NetconfHelloMessage(Document doc, NetconfHelloMessageAdditionalHeader additionalHeader) throws NetconfDocumentedException { super(doc); checkHelloMessage(doc); this.additionalHeader = additionalHeader; } - public NetconfHelloMessage(Document doc) { + public NetconfHelloMessage(Document doc) throws NetconfDocumentedException { this(doc, null); } @@ -43,20 +43,14 @@ public final class NetconfHelloMessage extends NetconfMessage { return additionalHeader== null ? Optional.absent() : Optional.of(additionalHeader); } - private static void checkHelloMessage(Document doc) { - try { - XmlElement.fromDomElementWithExpected(doc.getDocumentElement(), HELLO_TAG, - XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); + private static void checkHelloMessage(Document doc) throws NetconfDocumentedException { + XmlElement.fromDomElementWithExpected(doc.getDocumentElement(), HELLO_TAG, + XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); - } catch (IllegalArgumentException | IllegalStateException e) { - throw new IllegalArgumentException(String.format( - "Hello message invalid format, should contain %s tag from namespace %s, but is: %s", HELLO_TAG, - XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, XmlUtil.toString(doc)), e); - } } public static NetconfHelloMessage createClientHello(Iterable capabilities, - Optional additionalHeaderOptional) { + Optional additionalHeaderOptional) throws NetconfDocumentedException { Document doc = createHelloMessageDoc(capabilities); return additionalHeaderOptional.isPresent() ? new NetconfHelloMessage(doc, additionalHeaderOptional.get()) : new NetconfHelloMessage(doc); @@ -80,7 +74,7 @@ public final class NetconfHelloMessage extends NetconfMessage { return doc; } - public static NetconfHelloMessage createServerHello(Set capabilities, long sessionId) { + public static NetconfHelloMessage createServerHello(Set capabilities, long sessionId) throws NetconfDocumentedException { Document doc = createHelloMessageDoc(capabilities); Element sessionIdElement = doc.createElement(XmlNetconfConstants.SESSION_ID); sessionIdElement.setTextContent(Long.toString(sessionId)); diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageUtil.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageUtil.java index e4d97cf65a..49395d53d2 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageUtil.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageUtil.java @@ -10,9 +10,12 @@ package org.opendaylight.controller.netconf.util.messages; import com.google.common.base.Function; import com.google.common.collect.Collections2; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import javax.annotation.Nullable; @@ -21,39 +24,41 @@ import java.util.List; public final class NetconfMessageUtil { + private static final Logger logger = LoggerFactory.getLogger(NetconfMessageUtil.class); + private NetconfMessageUtil() {} - public static boolean isOKMessage(NetconfMessage message) { + public static boolean isOKMessage(NetconfMessage message) throws NetconfDocumentedException { return isOKMessage(message.getDocument()); } - public static boolean isOKMessage(Document document) { + public static boolean isOKMessage(Document document) throws NetconfDocumentedException { return isOKMessage(XmlElement.fromDomDocument(document)); } - public static boolean isOKMessage(XmlElement xmlElement) { + public static boolean isOKMessage(XmlElement xmlElement) throws NetconfDocumentedException { if(xmlElement.getChildElements().size() != 1) { return false; } return xmlElement.getOnlyChildElement().getName().equals(XmlNetconfConstants.OK); } - public static boolean isErrorMessage(NetconfMessage message) { + public static boolean isErrorMessage(NetconfMessage message) throws NetconfDocumentedException { return isErrorMessage(message.getDocument()); } - public static boolean isErrorMessage(Document document) { + public static boolean isErrorMessage(Document document) throws NetconfDocumentedException { return isErrorMessage(XmlElement.fromDomDocument(document)); } - public static boolean isErrorMessage(XmlElement xmlElement) { + public static boolean isErrorMessage(XmlElement xmlElement) throws NetconfDocumentedException { if(xmlElement.getChildElements().size() != 1) { return false; } return xmlElement.getOnlyChildElement().getName().equals(XmlNetconfConstants.RPC_ERROR); } - public static Collection extractCapabilitiesFromHello(Document doc) { + public static Collection extractCapabilitiesFromHello(Document doc) throws NetconfDocumentedException { XmlElement responseElement = XmlElement.fromDomDocument(doc); XmlElement capabilitiesElement = responseElement .getOnlyChildElementWithSameNamespace(XmlNetconfConstants.CAPABILITIES); @@ -64,7 +69,12 @@ public final class NetconfMessageUtil { @Override public String apply(@Nullable XmlElement input) { // Trim possible leading/tailing whitespace - return input.getTextContent().trim(); + try { + return input.getTextContent().trim(); + } catch (NetconfDocumentedException e) { + logger.trace("Error fetching inpit text content becauese {}",e); + return null; + } } }); diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java index 1fbae1ee2d..17ea3740fc 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java @@ -9,11 +9,16 @@ package org.opendaylight.controller.netconf.util.xml; import com.google.common.base.Optional; -import com.google.common.base.Preconditions; import com.google.common.base.Predicate; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException; +import org.opendaylight.controller.netconf.util.exception.UnexpectedElementException; +import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -34,6 +39,7 @@ import java.util.Map; public final class XmlElement { private final Element element; + private static final Logger logger = LoggerFactory.getLogger(XmlElement.class); private XmlElement(Element element) { this.element = element; @@ -47,27 +53,27 @@ public final class XmlElement { return new XmlElement(xml.getDocumentElement()); } - public static XmlElement fromString(String s) { + public static XmlElement fromString(String s) throws NetconfDocumentedException { try { return new XmlElement(XmlUtil.readXmlToElement(s)); } catch (IOException | SAXException e) { - throw new IllegalArgumentException("Unable to create from " + s, e); + throw NetconfDocumentedException.wrap(e); } } - public static XmlElement fromDomElementWithExpected(Element element, String expectedName) { + public static XmlElement fromDomElementWithExpected(Element element, String expectedName) throws NetconfDocumentedException { XmlElement xmlElement = XmlElement.fromDomElement(element); xmlElement.checkName(expectedName); return xmlElement; } - public static XmlElement fromDomElementWithExpected(Element element, String expectedName, String expectedNamespace) { + public static XmlElement fromDomElementWithExpected(Element element, String expectedName, String expectedNamespace) throws NetconfDocumentedException { XmlElement xmlElement = XmlElement.fromDomElementWithExpected(element, expectedName); xmlElement.checkNamespace(expectedNamespace); return xmlElement; } - private static Map extractNamespaces(Element typeElement) { + private static Map extractNamespaces(Element typeElement) throws NetconfDocumentedException { Map namespaces = new HashMap<>(); NamedNodeMap attributes = typeElement.getAttributes(); for (int i = 0; i < attributes.getLength(); i++) { @@ -78,7 +84,12 @@ public final class XmlElement { if (attribKey.equals(XmlUtil.XMLNS_ATTRIBUTE_KEY)) { prefix = ""; } else { - Preconditions.checkState(attribKey.startsWith(XmlUtil.XMLNS_ATTRIBUTE_KEY + ":")); + if (!attribKey.startsWith(XmlUtil.XMLNS_ATTRIBUTE_KEY + ":")){ + throw new NetconfDocumentedException("Attribute doesn't start with :", + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.invalid_value, + NetconfDocumentedException.ErrorSeverity.error); + } prefix = attribKey.substring(XmlUtil.XMLNS_ATTRIBUTE_KEY.length() + 1); } namespaces.put(prefix, attribute.getNodeValue()); @@ -87,19 +98,38 @@ public final class XmlElement { return namespaces; } - public void checkName(String expectedName) { - Preconditions.checkArgument(getName().equals(expectedName), "Expected %s xml element but was %s", expectedName, - getName()); + public void checkName(String expectedName) throws UnexpectedElementException { + if (!getName().equals(expectedName)){ + throw new UnexpectedElementException(String.format("Expected %s xml element but was %s", expectedName, + getName()), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.operation_failed, + NetconfDocumentedException.ErrorSeverity.error); + } } - public void checkNamespaceAttribute(String expectedNamespace) { - Preconditions.checkArgument(getNamespaceAttribute().equals(expectedNamespace), - "Unexpected namespace %s for element %s, should be %s", getNamespaceAttribute(), expectedNamespace); + public void checkNamespaceAttribute(String expectedNamespace) throws UnexpectedNamespaceException, MissingNameSpaceException { + if (!getNamespaceAttribute().equals(expectedNamespace)) + { + throw new UnexpectedNamespaceException(String.format("Unexpected namespace %s for element %s, should be %s", + getNamespaceAttribute(), + expectedNamespace), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.operation_failed, + NetconfDocumentedException.ErrorSeverity.error); + } } - public void checkNamespace(String expectedNamespace) { - Preconditions.checkArgument(getNamespace().equals(expectedNamespace), - "Unexpected namespace %s for element %s, should be %s", getNamespace(), expectedNamespace); + public void checkNamespace(String expectedNamespace) throws UnexpectedNamespaceException, MissingNameSpaceException { + if (!getNamespace().equals(expectedNamespace)) + { + throw new UnexpectedNamespaceException(String.format("Unexpected namespace %s for element %s, should be %s", + getNamespace(), + expectedNamespace), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.operation_failed, + NetconfDocumentedException.ErrorSeverity.error); + } } public String getName() { @@ -184,7 +214,11 @@ public final class XmlElement { return getChildElementsInternal(new ElementFilteringStrategy() { @Override public boolean accept(Element e) { - return XmlElement.fromDomElement(e).getNamespace().equals(namespace); + try { + return XmlElement.fromDomElement(e).getNamespace().equals(namespace); + } catch (MissingNameSpaceException e1) { + return false; + } } }); @@ -199,9 +233,14 @@ public final class XmlElement { }); } - public XmlElement getOnlyChildElement(String childName) { + public XmlElement getOnlyChildElement(String childName) throws NetconfDocumentedException { List nameElements = getChildElements(childName); - Preconditions.checkState(nameElements.size() == 1, "One element " + childName + " expected in " + toString()); + if (nameElements.size() != 1){ + throw new NetconfDocumentedException("One element " + childName + " expected in " + toString(), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.invalid_value, + NetconfDocumentedException.ErrorSeverity.error); + } return nameElements.get(0); } @@ -221,7 +260,7 @@ public final class XmlElement { } } - public XmlElement getOnlyChildElementWithSameNamespace(String childName) { + public XmlElement getOnlyChildElementWithSameNamespace(String childName) throws NetconfDocumentedException { return getOnlyChildElement(childName, getNamespace()); } @@ -233,7 +272,7 @@ public final class XmlElement { } } - public XmlElement getOnlyChildElementWithSameNamespace() { + public XmlElement getOnlyChildElementWithSameNamespace() throws NetconfDocumentedException { XmlElement childElement = getOnlyChildElement(); childElement.checkNamespace(getNamespace()); return childElement; @@ -249,7 +288,7 @@ public final class XmlElement { } } - public XmlElement getOnlyChildElement(final String childName, String namespace) { + public XmlElement getOnlyChildElement(final String childName, String namespace) throws NetconfDocumentedException { List children = getChildElementsWithinNamespace(namespace); children = Lists.newArrayList(Collections2.filter(children, new Predicate() { @Override @@ -257,38 +296,69 @@ public final class XmlElement { return xmlElement.getName().equals(childName); } })); - Preconditions.checkState(children.size() == 1, "One element %s:%s expected in %s but was %s", namespace, - childName, toString(), children.size()); + if (children.size() != 1){ + throw new NetconfDocumentedException(String.format("One element %s:%s expected in %s but was %s", namespace, + childName, toString(), children.size()), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.invalid_value, + NetconfDocumentedException.ErrorSeverity.error); + } + return children.get(0); } - public XmlElement getOnlyChildElement() { + public XmlElement getOnlyChildElement() throws NetconfDocumentedException { List children = getChildElements(); - Preconditions.checkState(children.size() == 1, "One element expected in %s but was %s", toString(), - children.size()); + if (children.size() != 1){ + throw new NetconfDocumentedException(String.format( "One element expected in %s but was %s", toString(), + children.size()), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.invalid_value, + NetconfDocumentedException.ErrorSeverity.error); + } return children.get(0); } - public String getTextContent() { + public String getTextContent() throws NetconfDocumentedException { Node textChild = element.getFirstChild(); - Preconditions.checkNotNull(textChild, "Child node expected, got null for " + getName() + " : " + element); - Preconditions.checkState(textChild instanceof Text, getName() + " should contain text." + - Text.class.getName() + " expected, got " + textChild); + if (null == textChild){ + throw new NetconfDocumentedException(String.format( "Child node expected, got null for " + getName() + " : " + element), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.invalid_value, + NetconfDocumentedException.ErrorSeverity.error); + } + if (!(textChild instanceof Text)){ + throw new NetconfDocumentedException(String.format(getName() + " should contain text." + + Text.class.getName() + " expected, got " + textChild), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.invalid_value, + NetconfDocumentedException.ErrorSeverity.error); + } String content = textChild.getTextContent(); // Trim needed return content.trim(); } - public String getNamespaceAttribute() { + public String getNamespaceAttribute() throws MissingNameSpaceException { String attribute = element.getAttribute(XmlUtil.XMLNS_ATTRIBUTE_KEY); - Preconditions.checkState(attribute != null && !attribute.equals(""), "Element %s must specify namespace", - toString()); + if (attribute == null || attribute.equals("")){ + throw new MissingNameSpaceException(String.format("Element %s must specify namespace", + toString()), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.operation_failed, + NetconfDocumentedException.ErrorSeverity.error); + } return attribute; } - public String getNamespace() { + public String getNamespace() throws MissingNameSpaceException { String namespaceURI = element.getNamespaceURI(); - Preconditions.checkState(namespaceURI != null, "No namespace defined for %s", this); + if (namespaceURI == null || namespaceURI.equals("")){ + throw new MissingNameSpaceException(String.format("No namespace defined for %s", this), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.operation_failed, + NetconfDocumentedException.ErrorSeverity.error); + } return namespaceURI; } @@ -297,7 +367,11 @@ public final class XmlElement { final StringBuilder sb = new StringBuilder("XmlElement{"); sb.append("name='").append(getName()).append('\''); if (element.getNamespaceURI() != null) { - sb.append(", namespace='").append(getNamespace()).append('\''); + try { + sb.append(", namespace='").append(getNamespace()).append('\''); + } catch (MissingNameSpaceException e) { + logger.trace("Missing namespace for element."); + } } sb.append('}'); return sb.toString(); @@ -316,7 +390,7 @@ public final class XmlElement { * namespace is returned with empty string as key. If no default namespace * is found value will be null. */ - public Map.Entry findNamespaceOfTextContent() { + public Map.Entry findNamespaceOfTextContent() throws NetconfDocumentedException { Map namespaces = extractNamespaces(element); String textContent = getTextContent(); int indexOfColon = textContent.indexOf(':'); @@ -333,7 +407,7 @@ public final class XmlElement { return Maps.immutableEntry(prefix, namespaces.get(prefix)); } - public List getChildElementsWithSameNamespace(final String childName) { + public List getChildElementsWithSameNamespace(final String childName) throws MissingNameSpaceException { List children = getChildElementsWithinNamespace(getNamespace()); return Lists.newArrayList(Collections2.filter(children, new Predicate() { @Override @@ -344,17 +418,22 @@ public final class XmlElement { } public void checkUnrecognisedElements(List recognisedElements, - XmlElement... additionalRecognisedElements) { + XmlElement... additionalRecognisedElements) throws NetconfDocumentedException { List childElements = getChildElements(); childElements.removeAll(recognisedElements); for (XmlElement additionalRecognisedElement : additionalRecognisedElements) { childElements.remove(additionalRecognisedElement); } - Preconditions.checkState(childElements.isEmpty(), "Unrecognised elements %s in %s", childElements, this); + if (!childElements.isEmpty()){ + throw new NetconfDocumentedException(String.format("Unrecognised elements %s in %s", childElements, this), + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.invalid_value, + NetconfDocumentedException.ErrorSeverity.error); + } } - public void checkUnrecognisedElements(XmlElement... additionalRecognisedElements) { - checkUnrecognisedElements(Collections. emptyList(), additionalRecognisedElements); + public void checkUnrecognisedElements(XmlElement... additionalRecognisedElements) throws NetconfDocumentedException { + checkUnrecognisedElements(Collections.emptyList(), additionalRecognisedElements); } @Override @@ -383,10 +462,10 @@ public final class XmlElement { public boolean hasNamespace() { try { getNamespaceAttribute(); - } catch (IllegalStateException e) { + } catch (MissingNameSpaceException e) { try { getNamespace(); - } catch (IllegalStateException e1) { + } catch (MissingNameSpaceException e1) { return false; } return true; diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java index d0be73843b..39a49544a5 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java @@ -43,6 +43,8 @@ public final class XmlNetconfConstants { public static final String SESSION_ID = "session-id"; // + // TODO duplicate + public static final String RFC4741_TARGET_NAMESPACE = "urn:ietf:params:xml:ns:netconf:base:1.0"; public static final String URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0 = "urn:ietf:params:xml:ns:netconf:base:1.0"; public static final String URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_1 = "urn:ietf:params:xml:ns:netconf:base:1.1"; public static final String URN_IETF_PARAMS_XML_NS_NETCONF_EXI_1_0 = "urn:ietf:params:xml:ns:netconf:exi:1.0"; diff --git a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/NetconfUtilTest.java b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/NetconfUtilTest.java index 85eeb30a07..b8605d8230 100644 --- a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/NetconfUtilTest.java +++ b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/NetconfUtilTest.java @@ -8,7 +8,6 @@ package org.opendaylight.controller.netconf.util; import org.junit.Test; -import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.w3c.dom.Document; @@ -22,7 +21,7 @@ public class NetconfUtilTest { public void testConflictingVersionDetection() throws Exception { Document document = XmlUtil.readXmlToDocument(getClass().getResourceAsStream("/netconfMessages/conflictingversion/conflictingVersionResponse.xml")); try{ - NetconfUtil.checkIsMessageOk(new NetconfMessage(document)); + NetconfUtil.checkIsMessageOk(document); fail(); }catch(IllegalStateException e){ assertThat(e.getMessage(), containsString("Optimistic lock failed. Expected parent version 21, was 18")); -- 2.36.6