2 * Copyright (c) 2018 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netconf.mdsal.connector.ops;
10 import static java.nio.charset.StandardCharsets.UTF_8;
12 import com.google.common.base.Strings;
13 import java.io.IOException;
14 import java.io.InputStream;
15 import java.net.MalformedURLException;
17 import java.net.URLConnection;
18 import java.net.URLStreamHandler;
19 import java.util.Base64;
20 import java.util.Optional;
21 import org.opendaylight.netconf.api.DocumentedException;
22 import org.opendaylight.netconf.api.xml.XmlElement;
23 import org.opendaylight.netconf.api.xml.XmlNetconfConstants;
24 import org.opendaylight.netconf.api.xml.XmlUtil;
25 import org.opendaylight.netconf.util.mapping.AbstractSingletonNetconfOperation;
26 import org.w3c.dom.Document;
27 import org.w3c.dom.Element;
28 import org.w3c.dom.NodeList;
29 import org.xml.sax.SAXException;
31 abstract class AbstractConfigOperation extends AbstractSingletonNetconfOperation {
32 static final String URL_KEY = "url";
33 static final String CONFIG_KEY = "config";
34 private static final int TIMEOUT_MS = 5000;
36 protected AbstractConfigOperation(final String netconfSessionIdForReporting) {
37 super(netconfSessionIdForReporting);
40 protected static NodeList getElementsByTagName(final XmlElement parent, final String key) throws
42 final Element domParent = parent.getDomElement();
43 final NodeList elementsByTagName;
45 if (Strings.isNullOrEmpty(domParent.getPrefix())) {
46 elementsByTagName = domParent.getElementsByTagName(key);
48 elementsByTagName = domParent.getElementsByTagNameNS(parent.getNamespace(), key);
51 return elementsByTagName;
54 static XmlElement getConfigElement(final XmlElement parent) throws DocumentedException {
55 final Optional<XmlElement> configElement = parent.getOnlyChildElementOptionally(CONFIG_KEY);
56 if (configElement.isPresent()) {
57 return configElement.get();
60 final Optional<XmlElement> urlElement = parent.getOnlyChildElementOptionally(URL_KEY);
61 if (!urlElement.isPresent()) {
62 throw new DocumentedException("Invalid RPC, neither <config> not <url> element is present",
63 DocumentedException.ErrorType.PROTOCOL,
64 DocumentedException.ErrorTag.MISSING_ELEMENT,
65 DocumentedException.ErrorSeverity.ERROR);
68 final Document document = getDocumentFromUrl(urlElement.get().getTextContent());
69 return XmlElement.fromDomElementWithExpected(document.getDocumentElement(), CONFIG_KEY,
70 XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
74 * Parses XML Document available at given URL.
76 * <p>JDK8 supports URL schemes that include http, https, file, and jar, but {@link URLStreamHandler}s for other
77 * protocols (e.g. ftp) may be available.
79 * @param url URL as defined in RFC 2396
80 * @see URL#URL(String, String, int, String)
82 private static Document getDocumentFromUrl(final String url) throws DocumentedException {
83 try (InputStream input = openConnection(new URL(url))) {
84 return XmlUtil.readXmlToDocument(input);
85 } catch (MalformedURLException e) {
86 throw new DocumentedException(url + " URL is invalid or unsupported", e,
87 DocumentedException.ErrorType.APPLICATION,
88 DocumentedException.ErrorTag.INVALID_VALUE,
89 DocumentedException.ErrorSeverity.ERROR);
90 } catch (IOException e) {
91 throw new DocumentedException("Could not open URL:" + url, e,
92 DocumentedException.ErrorType.APPLICATION,
93 DocumentedException.ErrorTag.OPERATION_FAILED,
94 DocumentedException.ErrorSeverity.ERROR);
95 } catch (SAXException e) {
96 throw new DocumentedException("Could not parse XML at" + url, e,
97 DocumentedException.ErrorType.APPLICATION,
98 DocumentedException.ErrorTag.OPERATION_FAILED,
99 DocumentedException.ErrorSeverity.ERROR);
103 private static InputStream openConnection(final URL url) throws IOException {
104 final URLConnection connection = url.openConnection();
105 connection.setConnectTimeout(TIMEOUT_MS);
106 connection.setReadTimeout(TIMEOUT_MS);
108 // Support Basic Authentication scheme, e.g. http://admin:admin@localhost:8000/config.conf
109 if (url.getUserInfo() != null) {
110 String basicAuth = "Basic " + Base64.getUrlEncoder().encodeToString(url.getUserInfo().getBytes(UTF_8));
111 connection.setRequestProperty("Authorization", basicAuth);
113 return connection.getInputStream();