X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fnetconf%2Fnetconf-api%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fnetconf%2Fapi%2FNetconfDocumentedException.java;h=e1e932b55a31e709a5618dc23818cc848d07e088;hp=57bd3dd6209d3248dc7c7b969ccaf6f5a33fbbf7;hb=b76c1bf326842dfc62db264f04ddb11373371715;hpb=61bad4207cc91cd14d8d38a255ad6549c20ff54e 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 57bd3dd620..e1e932b55a 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 @@ -8,12 +8,28 @@ package org.opendaylight.controller.netconf.api; -import org.opendaylight.controller.config.api.ConflictingVersionException; -import org.opendaylight.controller.config.api.ValidationException; +import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.ERROR_INFO; +import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.ERROR_MESSAGE; +import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.ERROR_SEVERITY; +import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.ERROR_TAG; +import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.ERROR_TYPE; +import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.RPC_ERROR; +import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.RPC_REPLY_KEY; +import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import org.opendaylight.controller.config.api.ConflictingVersionException; +import org.opendaylight.controller.config.api.ValidationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; /** * Checked exception to communicate an error that needs to be sent to the @@ -23,7 +39,26 @@ public class NetconfDocumentedException extends Exception { private static final long serialVersionUID = 1L; + private final static Logger LOG = LoggerFactory.getLogger( NetconfDocumentedException.class ); + private static final DocumentBuilderFactory BUILDER_FACTORY; + + static { + BUILDER_FACTORY = DocumentBuilderFactory.newInstance(); + try { + BUILDER_FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + BUILDER_FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false); + BUILDER_FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + BUILDER_FACTORY.setXIncludeAware(false); + BUILDER_FACTORY.setExpandEntityReferences(false); + } catch (ParserConfigurationException e) { + throw new ExceptionInInitializerError(e); + } + BUILDER_FACTORY.setNamespaceAware(true); + BUILDER_FACTORY.setCoalescing(true); + BUILDER_FACTORY.setIgnoringElementContentWhitespace(true); + BUILDER_FACTORY.setIgnoringComments(true); + } public enum ErrorType { transport, rpc, protocol, application; @@ -31,12 +66,37 @@ public class NetconfDocumentedException extends Exception { public String getTagValue() { return name(); } + + public static ErrorType from( String text ) { + try { + return valueOf( text ); + } + catch( Exception e ) { + return application; + } + } } public enum ErrorTag { - missing_attribute("missing-attribute"), unknown_element("unknown-element"), operation_not_supported( - "operation-not-supported"), bad_attribute("bad-attribute"), data_missing("data-missing"), operation_failed( - "operation-failed"), invalid_value("invalid-value"), malformed_message("malformed-message"); + access_denied("access-denied"), + bad_attribute("bad-attribute"), + bad_element("bad-element"), + data_exists("data-exists"), + data_missing("data-missing"), + in_use("in-use"), + invalid_value("invalid-value"), + lock_denied("lock-denied"), + malformed_message("malformed-message"), + missing_attribute("missing-attribute"), + missing_element("missing-element"), + operation_failed("operation-failed"), + operation_not_supported("operation-not-supported"), + resource_denied("resource-denied"), + rollback_failed("rollback-failed"), + too_big("too-big"), + unknown_attribute("unknown-attribute"), + unknown_element("unknown-element"), + unknown_namespace("unknown-namespace"); private final String tagValue; @@ -47,6 +107,17 @@ public class NetconfDocumentedException extends Exception { public String getTagValue() { return this.tagValue; } + + public static ErrorTag from( String text ) { + for( ErrorTag e: values() ) + { + if( e.getTagValue().equals( text ) ) { + return e; + } + } + + return operation_failed; + } } public enum ErrorSeverity { @@ -55,6 +126,15 @@ public class NetconfDocumentedException extends Exception { public String getTagValue() { return name(); } + + public static ErrorSeverity from( String text ) { + try { + return valueOf( text ); + } + catch( Exception e ) { + return error; + } + } } private final ErrorType errorType; @@ -62,6 +142,14 @@ public class NetconfDocumentedException extends Exception { private final ErrorSeverity errorSeverity; private final Map errorInfo; + public NetconfDocumentedException(String message) { + this(message, + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.invalid_value, + NetconfDocumentedException.ErrorSeverity.error + ); + } + public NetconfDocumentedException(final String message, final ErrorType errorType, final ErrorTag errorTag, final ErrorSeverity errorSeverity) { this(message, errorType, errorTag, errorSeverity, Collections. emptyMap()); @@ -110,6 +198,64 @@ public class NetconfDocumentedException extends Exception { ErrorSeverity.error, errorInfo); } + public static NetconfDocumentedException fromXMLDocument( Document fromDoc ) { + + ErrorType errorType = ErrorType.application; + ErrorTag errorTag = ErrorTag.operation_failed; + ErrorSeverity errorSeverity = ErrorSeverity.error; + Map errorInfo = null; + String errorMessage = ""; + + Node rpcReply = fromDoc.getDocumentElement(); + + // FIXME: BUG? - we only handle one rpc-error. + + NodeList replyChildren = rpcReply.getChildNodes(); + for( int i = 0; i < replyChildren.getLength(); i++ ) { + Node replyChild = replyChildren.item( i ); + if( RPC_ERROR.equals( replyChild.getNodeName() ) ) + { + NodeList rpcErrorChildren = replyChild.getChildNodes(); + for( int j = 0; j < rpcErrorChildren.getLength(); j++ ) + { + Node rpcErrorChild = rpcErrorChildren.item( j ); + if( ERROR_TYPE.equals( rpcErrorChild.getNodeName() ) ) { + errorType = ErrorType.from( rpcErrorChild.getTextContent() ); + } + else if( ERROR_TAG.equals( rpcErrorChild.getNodeName() ) ) { + errorTag = ErrorTag.from( rpcErrorChild.getTextContent() ); + } + else if( ERROR_SEVERITY.equals( rpcErrorChild.getNodeName() ) ) { + errorSeverity = ErrorSeverity.from( rpcErrorChild.getTextContent() ); + } + else if( ERROR_MESSAGE.equals( rpcErrorChild.getNodeName() ) ) { + errorMessage = rpcErrorChild.getTextContent(); + } + else if( ERROR_INFO.equals( rpcErrorChild.getNodeName() ) ) { + errorInfo = parseErrorInfo( rpcErrorChild ); + } + } + + break; + } + } + + return new NetconfDocumentedException( errorMessage, errorType, errorTag, errorSeverity, errorInfo ); + } + + private static Map parseErrorInfo( Node node ) { + Map infoMap = new HashMap<>(); + NodeList children = node.getChildNodes(); + for( int i = 0; i < children.getLength(); i++ ) { + Node child = children.item( i ); + if( child.getNodeType() == Node.ELEMENT_NODE ) { + infoMap.put( child.getNodeName(), child.getTextContent() ); + } + } + + return infoMap; + } + public ErrorType getErrorType() { return this.errorType; } @@ -126,6 +272,53 @@ public class NetconfDocumentedException extends Exception { return this.errorInfo; } + public Document toXMLDocument() { + Document doc = null; + try { + doc = BUILDER_FACTORY.newDocumentBuilder().newDocument(); + + Node rpcReply = doc.createElementNS( URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, RPC_REPLY_KEY ); + doc.appendChild( rpcReply ); + + Node rpcError = doc.createElementNS( URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, RPC_ERROR ); + rpcReply.appendChild( rpcError ); + + rpcError.appendChild( createTextNode( doc, ERROR_TYPE, getErrorType().getTagValue() ) ); + rpcError.appendChild( createTextNode( doc, ERROR_TAG, getErrorTag().getTagValue() ) ); + rpcError.appendChild( createTextNode( doc, ERROR_SEVERITY, getErrorSeverity().getTagValue() ) ); + rpcError.appendChild( createTextNode( doc, ERROR_MESSAGE, getLocalizedMessage() ) ); + + Map errorInfoMap = getErrorInfo(); + if( errorInfoMap != null && !errorInfoMap.isEmpty() ) { + /* + * + * message-id + * rpc + * + */ + + Node errorInfoNode = doc.createElementNS( URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, ERROR_INFO ); + errorInfoNode.setPrefix( rpcReply.getPrefix() ); + rpcError.appendChild( errorInfoNode ); + + for ( Entry entry : errorInfoMap.entrySet() ) { + errorInfoNode.appendChild( createTextNode( doc, entry.getKey(), entry.getValue() ) ); + } + } + } + catch( ParserConfigurationException e ) { + LOG.error( "Error outputting to XML document", e ); // this shouldn't happen + } + + return doc; + } + + private Node createTextNode( Document doc, String tag, String textContent ) { + Node node = doc.createElementNS( URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, tag ); + node.setTextContent( textContent ); + return node; + } + @Override public String toString() { return "NetconfDocumentedException{" + "message=" + getMessage() + ", errorType=" + this.errorType