├── javadoc
├── package-list
├── resources
│ └── inherit.gif
├── packages.html
├── script.js
├── stylesheet.css
├── allclasses-noframe.html
├── allclasses-frame.html
├── net
│ └── juniper
│ │ └── netconf
│ │ ├── package-frame.html
│ │ ├── class-use
│ │ ├── Device.html
│ │ ├── XMLBuilder.html
│ │ ├── LoadException.html
│ │ ├── NetconfSession.html
│ │ └── CommitException.html
│ │ ├── package-use.html
│ │ ├── package-tree.html
│ │ └── package-summary.html
├── overview-frame.html
├── index.html
├── deprecated-list.html
├── serialized-form.html
├── overview-tree.html
├── constant-values.html
├── overview-summary.html
└── help-doc.html
├── .mvn
└── wrapper
│ ├── maven-wrapper.jar
│ ├── maven-wrapper.properties
│ └── MavenWrapperDownloader.java
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── src
├── test
│ ├── resources
│ │ ├── sampleCliOutputReply.xml
│ │ ├── sampleMissingElement.xml
│ │ ├── sampleEmptyFPCTempRpcReply.xml
│ │ ├── sampleFPCTempRPCReply.xml
│ │ ├── log4j.properties
│ │ └── responses
│ │ │ └── lldpResponse.xml
│ └── java
│ │ └── net
│ │ └── juniper
│ │ └── netconf
│ │ ├── TestHelper.java
│ │ ├── LoadExceptionTest.java
│ │ ├── CommitExceptionTest.java
│ │ ├── DatastoreTest.java
│ │ ├── NetconfExceptionTest.java
│ │ ├── TestConstants.java
│ │ ├── element
│ │ ├── DatastoreTest.java
│ │ ├── RpcErrorTest.java
│ │ ├── HelloTest.java
│ │ └── RpcReplyLoadConfigResultsTest.java
│ │ ├── integration
│ │ ├── INTEGRATION_TESTS.md
│ │ ├── RUN-CRPD-CONTAINER.md
│ │ └── run-integration-tests.sh
│ │ └── XMLBuilderTest.java
└── main
│ └── java
│ └── net
│ └── juniper
│ └── netconf
│ ├── CommitException.java
│ ├── NetconfException.java
│ ├── LoadException.java
│ ├── element
│ ├── Datastore.java
│ └── AbstractNetconfElement.java
│ └── NetconfConstants.java
├── .gitignore
├── .editorconfig
├── examples
├── ShowChassis.java
├── CreateDevice.java
├── parse_system_info.java
├── parse_interface_info.java
├── EditConfiguration.java
└── snmp_config.java
├── .github
└── workflows
│ ├── maven.yml
│ └── codeql-analysis.yml
├── LICENSE
├── gradlew.bat
├── README.md
├── mvnw.cmd
└── gradlew
/javadoc/package-list:
--------------------------------------------------------------------------------
1 | net.juniper.netconf
2 |
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Juniper/netconf-java/HEAD/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/javadoc/resources/inherit.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Juniper/netconf-java/HEAD/javadoc/resources/inherit.gif
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Juniper/netconf-java/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
2 |
--------------------------------------------------------------------------------
/src/test/resources/sampleCliOutputReply.xml:
--------------------------------------------------------------------------------
1 |
6 | * The values defined here correspond to RFC 6241 (base 1.0) and related drafts 7 | * so that all modules reference a single, canonical source of truth rather than 8 | * scattering string literals throughout the codebase. 9 | *
10 | * This class is a simple constant holder and is therefore marked {@code final}
11 | * and given a private constructor to prevent instantiation.
12 | */
13 | public class TestConstants {
14 |
15 | public static final String CORRECT_HELLO = "
Three convenient constructors are provided so callers can supply: 17 | *
8 | * As defined by RFC-8342. 9 | * See ... 10 | */ 11 | public enum Datastore { 12 | /** 13 | * The running configuration datastore as defined by RFC-8342. 14 | */ 15 | RUNNING("running"), 16 | /** 17 | * The candidate configuration datastore as defined by RFC-8342. 18 | */ 19 | CANDIDATE("candidate"), 20 | /** 21 | * The startup configuration datastore as defined by RFC-8342. 22 | */ 23 | STARTUP("startup"), 24 | /** 25 | * The intended configuration datastore as defined by RFC-8342. 26 | */ 27 | INTENDED("intended"), 28 | /** 29 | * The operational state datastore as defined by RFC-8342. 30 | */ 31 | OPERATIONAL("operational"); 32 | 33 | private final String xmlName; 34 | 35 | Datastore(String xmlName) { 36 | this.xmlName = xmlName.toLowerCase(Locale.US); 37 | } 38 | 39 | /** 40 | * Returns the XML name (lowercase) for this datastore. 41 | */ 42 | @Override 43 | public String toString() { 44 | return xmlName; 45 | } 46 | 47 | /** 48 | * Returns the Datastore enum constant corresponding to the given XML name (case-insensitive). 49 | * @param name the XML name to lookup 50 | * @return the Datastore enum constant 51 | * @throws IllegalArgumentException if no matching constant exists 52 | */ 53 | public static Datastore fromXmlName(String name) { 54 | if (name == null) { 55 | throw new IllegalArgumentException("Datastore XML name cannot be null"); 56 | } 57 | String nameLc = name.toLowerCase(Locale.US); 58 | for (Datastore ds : values()) { 59 | if (ds.xmlName.equals(nameLc)) { 60 | return ds; 61 | } 62 | } 63 | throw new IllegalArgumentException("Unknown Datastore XML name: " + name); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/net/juniper/netconf/integration/RUN-CRPD-CONTAINER.md: -------------------------------------------------------------------------------- 1 | # Running Juniper cRPD for integration tests 2 | 3 | This project’s integration tests need a live NETCONF endpoint. 4 | You can spin up Juniper’s containerised Routing Protocol Daemon (**cRPD**) locally in < 1 minute. 5 | 6 | --- 7 | 8 | ## 1 . Prerequisites 9 | 10 | * **Docker + Colima** (or Docker Desktop) on macOS 11 | ```bash 12 | brew install colima docker docker-compose 13 | colima start # arm64 by default; add --arch x86_64 if you need an amd64 VM 14 | ``` 15 | 16 | * **cRPD image** (free evaluation tarball from Juniper) 17 | Place it under `src/test/resources/` as shown below. 18 | 19 | --- 20 | 21 | ## 2 . Load the image into Docker 22 | 23 | ```bash 24 | docker load < src/test/resources/junos-routing-crpd-docker-23.2R1.13-arm64.tgz 25 | # or …-amd64… if you’re running a colima --arch x86_64 VM 26 | ``` 27 | 28 | Verify: 29 | 30 | ```bash 31 | docker images | grep crpd 32 | # crpd 23.2R1.13 0cf5ad… 498MB 33 | ``` 34 | 35 | --- 36 | 37 | ## 3 . Start cRPD with NETCONF and SSH exposed 38 | 39 | ```bash 40 | docker run -d --name crpd1 --privileged \ 41 | -p 2222:22 \ # SSH 42 | -p 1830:830 \ # NETCONF 43 | crpd:23.2R1.13 44 | ``` 45 | 46 | Wait ~40 s, then configure a test user and enable NETCONF: 47 | 48 | ```bash 49 | docker exec -ti crpd1 cli 50 | 51 | # inside Junos CLI 52 | configure 53 | set system root-authentication plain-text-password 54 | # (enter a password, e.g. Junos123) 55 | set system login user test uid 2000 class super-user 56 | set system login user test authentication plain-text-password 57 | # (password: test1234) 58 | 59 | set system services ssh 60 | set system services netconf ssh 61 | commit and-quit 62 | ``` 63 | 64 | --- 65 | 66 | ## 4 . Run the integration test wrapper 67 | 68 | ```bash 69 | ./src/test/java/net/juniper/netconf/integration/run-integration-tests.sh \ 70 | --username test \ 71 | --password test1234 \ 72 | --host localhost \ 73 | --port 1830 74 | ``` 75 | 76 | The script builds the library, spins up JUnit tests, and targets the NETCONF service you just started. 77 | 78 | --- 79 | 80 | ### Cleaning up 81 | 82 | ```bash 83 | docker rm -f crpd1 # stop & remove the container 84 | ``` 85 | 86 | That’s it! You now have a repeatable way to launch a Junos device for automated NETCONF testing. -------------------------------------------------------------------------------- /src/main/java/net/juniper/netconf/NetconfConstants.java: -------------------------------------------------------------------------------- 1 | package net.juniper.netconf; 2 | 3 | /** 4 | * Centralised collection of string literals and protocol constants used 5 | * throughout the NETCONF client library. 6 | *
7 | * The class is {@code final} and has a private constructor – it cannot be 8 | * instantiated or extended. All members are {@code public static final} 9 | * to encourage direct use without additional indirection. 10 | *
11 | * 12 | * @author Jonas Glass 13 | */ 14 | public class NetconfConstants { 15 | 16 | /* ------------------------------------------------------------------ 17 | * Framing protocol 18 | * ------------------------------------------------------------------ */ 19 | 20 | /** 21 | * Device prompt used by the NETCONF chunked framing protocol. 22 | * 23 | * @see RFC 6242 §4.1 24 | */ 25 | public static final String DEVICE_PROMPT = "]]>]]>"; 26 | 27 | /* ------------------------------------------------------------------ 28 | * XML preamble & namespaces 29 | * ------------------------------------------------------------------ */ 30 | 31 | /** 32 | * XML declaration emitted at the top of NETCONF messages. 33 | */ 34 | public static final String XML_VERSION = ""; 35 | 36 | /** 37 | * XML namespace for NETCONF Base 1.0 38 | * 39 | * @see RFC 6241 §8.1 40 | */ 41 | public static final String URN_XML_NS_NETCONF_BASE_1_0 = "urn:ietf:params:xml:ns:netconf:base:1.0"; 42 | 43 | /** 44 | * URI form of the NETCONF Base 1.0 capability identifier. 45 | * 46 | * @see RFC 6241 §8.1 47 | */ 48 | public static final String URN_IETF_PARAMS_NETCONF_BASE_1_0 = "urn:ietf:params:netconf:base:1.0"; 49 | 50 | /* ------------------------------------------------------------------ 51 | * Misc helpers 52 | * ------------------------------------------------------------------ */ 53 | 54 | /** Empty line helper constant. */ 55 | public static final String EMPTY_LINE = ""; 56 | 57 | /** Line feed (Unix‑style newline). */ 58 | public static final String LF = "\n"; 59 | 60 | /** Carriage return (use with {@code LF} for CRLF sequences). */ 61 | public static final String CR = "\r"; 62 | 63 | /** UTF‑8 charset literal used throughout the library. */ 64 | public static final String CHARSET_UTF8 = "utf-8"; 65 | 66 | /** 67 | * Not instantiable – utility holder only. 68 | */ 69 | private NetconfConstants() { /* no‑op */ } 70 | } 71 | -------------------------------------------------------------------------------- /src/test/java/net/juniper/netconf/element/RpcErrorTest.java: -------------------------------------------------------------------------------- 1 | package net.juniper.netconf.element; 2 | 3 | import net.juniper.netconf.element.RpcError.ErrorSeverity; 4 | import net.juniper.netconf.element.RpcError.ErrorTag; 5 | import net.juniper.netconf.element.RpcError.ErrorType; 6 | import net.juniper.netconf.element.RpcError.RpcErrorInfo; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static org.assertj.core.api.Assertions.*; 10 | 11 | /** 12 | * Unit tests for the {@link RpcError} record and its helper enums / builder. 13 | */ 14 | class RpcErrorTest { 15 | 16 | @Test 17 | void builderCreatesEquivalentRecord() { 18 | RpcErrorInfo info = RpcErrorInfo.builder() 19 | .badAttribute("attr") 20 | .sessionId("101") 21 | .build(); 22 | 23 | RpcError fromBuilder = RpcError.builder() 24 | .errorType(ErrorType.RPC) 25 | .errorTag(ErrorTag.INVALID_VALUE) 26 | .errorSeverity(ErrorSeverity.ERROR) 27 | .errorPath("/interfaces/interface[name='xe-0/0/0']") 28 | .errorMessage("invalid value") 29 | .errorMessageLanguage("en") 30 | .errorInfo(info) 31 | .build(); 32 | 33 | RpcError direct = new RpcError(ErrorType.RPC, 34 | ErrorTag.INVALID_VALUE, 35 | ErrorSeverity.ERROR, 36 | "/interfaces/interface[name='xe-0/0/0']", 37 | "invalid value", 38 | "en", 39 | info); 40 | 41 | assertThat(fromBuilder).isEqualTo(direct); 42 | assertThat(fromBuilder.hashCode()).isEqualTo(direct.hashCode()); 43 | } 44 | 45 | @Test 46 | void enumsRoundTripFromString() { 47 | assertThat(ErrorType.from("protocol")).isEqualTo(ErrorType.PROTOCOL); 48 | assertThat(ErrorTag.from("unknown-element")).isEqualTo(ErrorTag.UNKNOWN_ELEMENT); 49 | assertThat(ErrorSeverity.from("warning")).isEqualTo(ErrorSeverity.WARNING); 50 | 51 | // unknown returns null 52 | assertThat(ErrorTag.from("does-not-exist")).isNull(); 53 | } 54 | 55 | @Test 56 | void toStringContainsKeyFields() { 57 | RpcError error = RpcError.builder() 58 | .errorType(ErrorType.TRANSPORT) 59 | .errorTag(ErrorTag.LOCK_DENIED) 60 | .errorSeverity(ErrorSeverity.ERROR) 61 | .errorMessage("lock denied") 62 | .build(); 63 | 64 | String txt = error.toString(); 65 | assertThat(txt).contains("TRANSPORT") 66 | .contains("LOCK_DENIED") 67 | .contains("lock denied"); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /javadoc/overview-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 || 22 | | 23 |
| All Classes
29 |
30 |
31 | Packages
32 | |
62 |
66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "master" ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "master" ] 20 | schedule: 21 | - cron: '22 13 * * 3' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'java' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v3 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v2 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | 52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 53 | # queries: security-extended,security-and-quality 54 | 55 | 56 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 57 | # If this step fails, then you should remove it and run the build manually (see below) 58 | - name: Autobuild 59 | uses: github/codeql-action/autobuild@v2 60 | 61 | # ℹ️ Command-line programs to run using the OS shell. 62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 63 | 64 | # If the Autobuild fails above, remove it and uncomment the following three lines. 65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 66 | 67 | # - run: | 68 | # echo "Run, Build Application using script" 69 | # ./location_of_script_within_repo/buildscript.sh 70 | 71 | - name: Perform CodeQL Analysis 72 | uses: github/codeql-action/analyze@v2 73 | -------------------------------------------------------------------------------- /javadoc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 |Copyright 2018, Juniper Networks, Inc.
121 | 122 | 123 | -------------------------------------------------------------------------------- /src/test/java/net/juniper/netconf/XMLBuilderTest.java: -------------------------------------------------------------------------------- 1 | package net.juniper.netconf; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import static org.assertj.core.api.Assertions.assertThat; 5 | import static org.assertj.core.api.Assertions.assertThatThrownBy; 6 | 7 | import java.util.Arrays; 8 | import java.util.Collections; 9 | 10 | public class XMLBuilderTest { 11 | 12 | @Test 13 | public void createNewConfig_twoElements_createsExpectedXML() throws Exception { 14 | XMLBuilder builder = new XMLBuilder(); 15 | XML xml = builder.createNewConfig("system", "services"); 16 | assertThat(xml.toString()) 17 | .containsIgnoringWhitespaces( 18 | "Copyright 2018, Juniper Networks, Inc.
121 | 122 | 123 | -------------------------------------------------------------------------------- /javadoc/net/juniper/netconf/class-use/XMLBuilder.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |Copyright 2018, Juniper Networks, Inc.
121 | 122 | 123 | -------------------------------------------------------------------------------- /javadoc/net/juniper/netconf/class-use/LoadException.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |Copyright 2018, Juniper Networks, Inc.
121 | 122 | 123 | -------------------------------------------------------------------------------- /.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | https://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | import java.io.File; 21 | import java.io.FileInputStream; 22 | import java.io.FileOutputStream; 23 | import java.io.IOException; 24 | import java.net.URL; 25 | import java.nio.channels.Channels; 26 | import java.nio.channels.ReadableByteChannel; 27 | import java.util.Properties; 28 | 29 | public class MavenWrapperDownloader { 30 | 31 | /** 32 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 33 | */ 34 | private static final String DEFAULT_DOWNLOAD_URL = 35 | "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"; 36 | 37 | /** 38 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 39 | * use instead of the default one. 40 | */ 41 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 42 | ".mvn/wrapper/maven-wrapper.properties"; 43 | 44 | /** 45 | * Path where the maven-wrapper.jar will be saved to. 46 | */ 47 | private static final String MAVEN_WRAPPER_JAR_PATH = 48 | ".mvn/wrapper/maven-wrapper.jar"; 49 | 50 | /** 51 | * Name of the property which should be used to override the default download url for the wrapper. 52 | */ 53 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 54 | 55 | public static void main(String args[]) { 56 | System.out.println("- Downloader started"); 57 | File baseDirectory = new File(args[0]); 58 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 59 | 60 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 61 | // wrapperUrl parameter. 62 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 63 | String url = DEFAULT_DOWNLOAD_URL; 64 | if(mavenWrapperPropertyFile.exists()) { 65 | FileInputStream mavenWrapperPropertyFileInputStream = null; 66 | try { 67 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 68 | Properties mavenWrapperProperties = new Properties(); 69 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 70 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 71 | } catch (IOException e) { 72 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 73 | } finally { 74 | try { 75 | if(mavenWrapperPropertyFileInputStream != null) { 76 | mavenWrapperPropertyFileInputStream.close(); 77 | } 78 | } catch (IOException e) { 79 | // Ignore ... 80 | } 81 | } 82 | } 83 | System.out.println("- Downloading from: : " + url); 84 | 85 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 86 | if(!outputFile.getParentFile().exists()) { 87 | if(!outputFile.getParentFile().mkdirs()) { 88 | System.out.println( 89 | "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 90 | } 91 | } 92 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 93 | try { 94 | downloadFileFromURL(url, outputFile); 95 | System.out.println("Done"); 96 | System.exit(0); 97 | } catch (Throwable e) { 98 | System.out.println("- Error downloading"); 99 | e.printStackTrace(); 100 | System.exit(1); 101 | } 102 | } 103 | 104 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 105 | URL website = new URL(urlString); 106 | ReadableByteChannel rbc; 107 | rbc = Channels.newChannel(website.openStream()); 108 | FileOutputStream fos = new FileOutputStream(destination); 109 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 110 | fos.close(); 111 | rbc.close(); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /javadoc/serialized-form.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |Copyright 2018, Juniper Networks, Inc.
144 | 145 | 146 | -------------------------------------------------------------------------------- /javadoc/net/juniper/netconf/package-use.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 || Class and Description | 83 |
|---|
| CommitException
87 | Describes exceptions related to commit operation
88 | |
89 |
| NetconfException
92 | Describes exceptions related to establishing Netconf session.
93 | |
94 |
| NetconfSession
97 | A
99 | NetconfSession object is used to call the Netconf driver
98 | methods. |
100 |
| XML
103 | An
105 | XML object represents XML content and provides methods to
104 | manipulate it. |
106 |
Copyright 2018, Juniper Networks, Inc.
158 | 159 | 160 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | netconf-java 2 | ============ 3 | 4 | **A modernized Java library for NETCONF (now Java 17‑compatible)** 5 | 6 | Java library for NETCONF 7 | 8 | SUPPORT 9 | ======= 10 | 11 | This software is not officially supported by Juniper Networks, but by a team dedicated to helping customers, 12 | partners, and the development community. To report bug-fixes, issues, suggestions, please raise issues 13 | or even better submit pull requests on GitHub. 14 | 15 | REQUIREMENTS 16 | ============ 17 | 18 | * [OpenJDK 17](https://openjdk.org/projects/jdk/17/) or later 19 | * [Maven](https://maven.apache.org/download.cgi) if you want to build using `mvn` [Supported from v2.1.1]. 20 | * [Gradle 8+](https://gradle.org/releases/) if you prefer a Gradle build (`./gradlew build`) 21 | 22 | Building 23 | ======== 24 | You can build the project using **Maven** or **Gradle**. 25 | 26 | ### Maven 27 | ```bash 28 | mvn clean package 29 | ``` 30 | 31 | ### Gradle 32 | ```bash 33 | ./gradlew clean build 34 | ``` 35 | (The wrapper script downloads the correct Gradle version automatically.) 36 | 37 | Releases 38 | ======== 39 | Releases contain source code only. Due to changing JDK licensing, jar files are not released. 40 | User may download the source code and compile it with desired JDK version. 41 | 42 | * Instructions to build 43 | * Download Source Code for the required release 44 | * Compile the code and build the jar using your chosen JDK version 45 | * Use the jar file 46 | 47 | * Instructions to build using `mvn` 48 | * Download Source Code for the required release 49 | * Compile the code and build the jar using `mvn package` 50 | * Use the jar file from (source to netconf-java)/netconf-java/target 51 | * Use `mvn versions:display-dependency-updates` to identify possible target versions for dependencies 52 | 53 | ======= 54 | 55 | v2.2.0 56 | ------ 57 | * Java 17 baseline; compiled with `--release 17` 58 | * Gradle build added alongside Maven 59 | * SpotBugs upgraded to 6.x 60 | * Added **:confirmed-commit:1.1** support (`commitConfirm(timeout, persist)` and `cancelCommit(persistId)`) 61 | * Added **killSession(String)** helper for RFC 6241 §7.9 62 | * Auto‑inject base 1.1 capability in <hello> exchange 63 | * Gradle wrapper committed; GitHub Actions now builds Maven *and* Gradle 64 | * Expanded Javadoc and SpotBugs clean‑up 65 | 66 | v2.1.1 67 | ------ 68 | 69 | * Fixed `mvn` build issues 70 | 71 | v2.0.0 72 | ------ 73 | 74 | * Replaced the ssh library with [JSch](http://www.jcraft.com/jsch/) 75 | * Adds support for new ssh crypto algorithms 76 | * More modern ssh implementation 77 | * Added support for importing and building the library with maven 78 | * Added FindBugs code testing to maven build 79 | 80 | This is a breaking change to the API. New Device objects are now created using a builder. 81 | Example: 82 | 83 | ```Java 84 | Device device = Device.builder().hostName("hostname") 85 | .userName("username") 86 | .password("password") 87 | .connectionTimeout(2000) 88 | .hostKeysFileName("hostKeysFileName") 89 | .build(); 90 | ``` 91 | 92 | SYNOPSIS 93 | ======== 94 | 95 | ```Java 96 | import java.io.IOException; 97 | import javax.xml.parsers.ParserConfigurationException; 98 | import net.juniper.netconf.NetconfException; 99 | import org.xml.sax.SAXException; 100 | 101 | import net.juniper.netconf.XML; 102 | import net.juniper.netconf.Device; 103 | 104 | public class ShowInterfaces { 105 | public static void main(String args[]) throws NetconfException, 106 | ParserConfigurationException, SAXException, IOException { 107 | 108 | //Create device 109 | Device device = Device.builder() 110 | .hostName("hostname") 111 | .userName("username") 112 | .password("password") 113 | .connectionTimeout(2000) 114 | .hostKeysFileName("hostKeysFileName") 115 | .build(); 116 | device.connect(); 117 | 118 | //Send RPC and receive RPC Reply as XML 119 | XML rpc_reply = device.executeRPC("get-interface-information"); 120 | /* OR 121 | * device.executeRPC("Copyright 2018, Juniper Networks, Inc.
152 | 153 | 154 | -------------------------------------------------------------------------------- /javadoc/net/juniper/netconf/package-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |Copyright 2018, Juniper Networks, Inc.
148 | 149 | 150 | -------------------------------------------------------------------------------- /javadoc/net/juniper/netconf/class-use/NetconfSession.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 || Modifier and Type | 86 |Field and Description | 87 |
|---|---|
private NetconfSession |
91 | Device.netconfSession |
92 |
| Modifier and Type | 99 |Method and Description | 100 |
|---|---|
private NetconfSession |
104 | Device.createNetconfSession()
105 | Create a new Netconf session.
106 | |
107 |
Copyright 2018, Juniper Networks, Inc.
161 | 162 | 163 | -------------------------------------------------------------------------------- /javadoc/net/juniper/netconf/package-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 || Class | 81 |Description | 82 |
|---|---|
| Device | 86 |
87 | A
88 | Device is used to define a Netconf server. |
89 |
| NetconfSession | 92 |
93 | A
95 | NetconfSession object is used to call the Netconf driver
94 | methods. |
96 |
| XML | 99 |
100 | An
102 | XML object represents XML content and provides methods to
101 | manipulate it. |
103 |
| XMLBuilder | 106 |
107 | An
109 | XMLBuilder is used to create an XML object.This is useful to
108 | create XML RPC's and configurations. |
110 |
| Exception | 119 |Description | 120 |
|---|---|
| CommitException | 124 |
125 | Describes exceptions related to commit operation
126 | |
127 |
| LoadException | 130 |
131 | Describes exceptions related to load operation
132 | |
133 |
| NetconfException | 136 |
137 | Describes exceptions related to establishing Netconf session.
138 | |
139 |
Copyright 2018, Juniper Networks, Inc.
191 | 192 | 193 | -------------------------------------------------------------------------------- /javadoc/constant-values.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 || Modifier and Type | 88 |Constant Field | 89 |Value | 90 |
|---|---|---|
94 |
95 | private static final int |
96 | DEFAULT_NETCONF_PORT |
97 | 830 |
98 |
101 |
102 | private static final int |
103 | DEFAULT_TIMEOUT |
104 | 5000 |
105 |
| Modifier and Type | 114 |Constant Field | 115 |Value | 116 |
|---|---|---|
120 |
121 | private static final String |
122 | CANDIDATE_CONFIG |
123 | "candidate" |
124 |
127 |
128 | private static final String |
129 | EMPTY_CONFIGURATION_TAG |
130 | "<configuration></configuration>" |
131 |
134 |
135 | private static final String |
136 | RUNNING_CONFIG |
137 | "running" |
138 |
Copyright 2018, Juniper Networks, Inc.
190 | 191 | 192 | -------------------------------------------------------------------------------- /javadoc/overview-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
32 |
33 |
|
45 | 46 | 47 | | 48 ||||||||||
| 52 | PREV 53 | NEXT | 54 |55 | FRAMES 56 | NO FRAMES 57 | 64 | 67 | 68 | | 69 ||||||||||
| 79 | Packages | 80 ||
| ch.ethz.ssh2 | 83 |84 | |
| ch.ethz.ssh2.auth | 87 |88 | |
| ch.ethz.ssh2.channel | 91 |92 | |
| ch.ethz.ssh2.crypto | 95 |96 | |
| ch.ethz.ssh2.crypto.cipher | 99 |100 | |
| ch.ethz.ssh2.crypto.dh | 103 |104 | |
| ch.ethz.ssh2.crypto.digest | 107 |108 | |
| ch.ethz.ssh2.log | 111 |112 | |
| ch.ethz.ssh2.packets | 115 |116 | |
| ch.ethz.ssh2.sftp | 119 |120 | |
| ch.ethz.ssh2.signature | 123 |124 | |
| ch.ethz.ssh2.transport | 127 |128 | |
| ch.ethz.ssh2.util | 131 |132 | |
| net.juniper.netconf | 135 |136 | |
140 |
149 |
150 |
|
162 | 163 | 164 | | 165 ||||||||||
| 169 | PREV 170 | NEXT | 171 |172 | FRAMES 173 | NO FRAMES 174 | 181 | 184 | 185 | | 186 ||||||||||
| Modifier and Type | 86 |Method and Description | 87 |
|---|---|
void |
91 | Device.commit()
92 | Commit the candidate configuration.
93 | |
94 |
void |
97 | Device.commitConfirm(long seconds)
98 | Commit the candidate configuration, temporarily.
99 | |
100 |
void |
103 | NetconfSession.commitFull()
104 | Commit the candidate configuration and rebuild the config database.
105 | |
106 |
void |
109 | Device.commitFull()
110 | Commit full is an unsupported Juniper command that will commit the config and then signal all processes to
111 | check the configuration for changes.
112 | |
113 |
void |
116 | Device.commitThisConfiguration(String configFile,
117 | String loadType)
118 | Loads and commits the candidate configuration, Configuration can be in
119 | text/xml format.
120 | |
121 |
Copyright 2018, Juniper Networks, Inc.
175 | 176 | 177 | -------------------------------------------------------------------------------- /javadoc/help-doc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
31 |
32 |
|
44 | 45 | 46 | | 47 ||||||||||
| 51 | PREV 52 | NEXT | 53 |54 | FRAMES 55 | NO FRAMES 56 | 63 | 66 | 67 | | 68 ||||||||||
81 | 82 |84 |83 | The Overview page is the front page of this API document and provides a list of all packages with a summary for each. This page can also contain an overall description of the set of packages.
87 | 88 |92 |89 | Each package has a page that contains a list of its classes and interfaces, with a summary for each. This page can contain four categories:
90 |
91 |- Interfaces (italic)
- Classes
- Exceptions
- Errors
95 | 96 |104 |97 | Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:
98 |
103 | Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.- Class inheritance diagram
- Direct Subclasses
- All Known Subinterfaces
- All Known Implementing Classes
- Class/interface declaration
- Class/interface description 99 |
100 |
- Nested Class Summary
- Field Summary
- Constructor Summary
- Method Summary 101 |
102 |
- Field Detail
- Constructor Detail
- Method Detail
107 | There is a Class Hierarchy page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. The classes are organized by inheritance structure starting with110 |java.lang.Object. The interfaces do not inherit fromjava.lang.Object.108 |
109 |- When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.
- When viewing a particular package, class or interface page, clicking "Tree" displays the hierarchy for only that package.
113 | The Deprecated API page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to improvements, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.114 |
117 | The Index contains an alphabetic list of all classes, interfaces, constructors, methods, and fields.118 |
124 |
128 |
129 |
130 | This help file applies to API documentation generated using the standard doclet.
131 |
132 |
133 |
142 |
143 |
|
155 | 156 | 157 | | 158 ||||||||||
| 162 | PREV 163 | NEXT | 164 |165 | FRAMES 166 | NO FRAMES 167 | 174 | 177 | 178 | | 179 ||||||||||
23 | * Each subclass wraps a {@link org.w3c.dom.Document} so that: 24 | *
74 | * Internally delegates to {@link #createDocumentBuilderFactory()} to ensure 75 | * all security features are applied consistently. 76 | * 77 | * @return a brand‑new, empty {@link Document} 78 | * @throws IllegalStateException if the platform’s XML parser cannot be configured 79 | */ 80 | protected static Document createBlankDocument() { 81 | try { 82 | return createDocumentBuilderFactory().newDocumentBuilder().newDocument(); 83 | } catch (final ParserConfigurationException e) { 84 | throw new IllegalStateException("Unable to create document builder", e); 85 | } 86 | } 87 | 88 | /** 89 | * Returns a pre‑configured {@link DocumentBuilderFactory} with 90 | * namespace awareness enabled. Additional hardening options 91 | * (e.g. disallowing DTDs) can be added here centrally so every 92 | * NETCONF element parser benefits. 93 | * 94 | * @return a namespace‑aware {@link DocumentBuilderFactory} 95 | */ 96 | protected static DocumentBuilderFactory createDocumentBuilderFactory() { 97 | final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); 98 | documentBuilderFactory.setNamespaceAware(true); 99 | return documentBuilderFactory; 100 | } 101 | 102 | /** 103 | * Serialises a DOM {@link Document} to its XML string representation. 104 | *
105 | * The XML declaration is omitted because NETCONF frames are always UTF‑8
106 | * and the declaration is not required on the wire.
107 | *
108 | * @param document the document to serialise; must not be {@code null}
109 | * @return XML string (no declaration)
110 | * @throws IllegalStateException if a {@link TransformerException} occurs
111 | */
112 | protected static String createXml(final Document document) {
113 | try {
114 | final TransformerFactory transformerFactory = TransformerFactory.newInstance();
115 | final Transformer transformer = transformerFactory.newTransformer();
116 | transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
117 | final StringWriter stringWriter = new StringWriter();
118 | transformer.transform(new DOMSource(document), new StreamResult(stringWriter));
119 | return stringWriter.toString();
120 | } catch (final TransformerException e) {
121 | throw new IllegalStateException("Unable to transform document to XML", e);
122 | }
123 | }
124 |
125 | /**
126 | * Convenience helper that builds an XPath expression matching a NETCONF
127 | * element in the base 1.0 namespace with the specified local‑name.
128 | *
129 | * @param elementName local name (e.g. {@code "rpc-reply"})
130 | * @return an XPath string scoped to the NETCONF base namespace
131 | */
132 | protected static String getXpathFor(final String elementName) {
133 | return format("/*[namespace-uri()='urn:ietf:params:xml:ns:netconf:base:1.0' and local-name()='%s']", elementName);
134 | }
135 |
136 | /**
137 | * Appends a child element (with optional text content) to the given parent,
138 | * using the NETCONF base 1.0 namespace and the provided prefix.
139 | *
140 | * @param document owner document
141 | * @param parentElement element to which the new child is appended
142 | * @param namespacePrefix namespace prefix to set on the new element
143 | * @param elementName local name of the child element
144 | * @param text text content; if {@code null} the element is skipped
145 | * @return the newly created element, or {@code null} if {@code text} was {@code null}
146 | */
147 | protected static Element appendElementWithText(
148 | final Document document,
149 | final Element parentElement,
150 | final String namespacePrefix,
151 | final String elementName,
152 | final String text) {
153 |
154 | if (text != null) {
155 | final Element childElement = document.createElementNS(NetconfConstants.URN_XML_NS_NETCONF_BASE_1_0, elementName);
156 | childElement.setPrefix(namespacePrefix);
157 | childElement.setTextContent(text);
158 | parentElement.appendChild(childElement);
159 | return childElement;
160 | } else {
161 | return null;
162 | }
163 | }
164 |
165 | /**
166 | * Safely retrieves an attribute value from the supplied DOM {@link Element}.
167 | *
168 | * @param element the element to query; may be {@code null}
169 | * @param attributeName the local name of the attribute
170 | * @return the attribute value if the element is non‑null and the attribute
171 | * exists; otherwise {@code null}
172 | */
173 | protected static String getAttribute(final Element element, final String attributeName) {
174 | if (element != null && element.hasAttribute(attributeName)) {
175 | return element.getAttribute(attributeName);
176 | } else {
177 | return null;
178 | }
179 | }
180 |
181 | /**
182 | * Returns the trimmed text content of a DOM {@link Element}.
183 | *
184 | * @param element the element whose {@code getTextContent()} should be read;
185 | * may be {@code null}
186 | * @return trimmed text or {@code null} if the element is {@code null}
187 | */
188 | protected static String getTextContent(final Element element) {
189 | if (element == null) {
190 | return null;
191 | } else {
192 | return trim(element.getTextContent());
193 | }
194 | }
195 |
196 | /**
197 | * Convenience null‑safe {@link String#trim()} wrapper.
198 | *
199 | * @param string the input string; may be {@code null}
200 | * @return a trimmed copy of {@code string}, or {@code null} if the input
201 | * was {@code null}
202 | */
203 | protected static String trim(final String string) {
204 | return string == null ? null : string.trim();
205 | }
206 |
207 | @Override
208 | public boolean equals(Object o) {
209 | if (this == o) return true;
210 | if (o == null || getClass() != o.getClass()) return false;
211 | AbstractNetconfElement that = (AbstractNetconfElement) o;
212 | return xml.equals(that.xml);
213 | }
214 |
215 | @Override
216 | public int hashCode() {
217 | return xml.hashCode();
218 | }
219 |
220 | @Override
221 | public String toString() {
222 | return getClass().getSimpleName() + "{}";
223 | }
224 | }
225 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 | # SPDX-License-Identifier: Apache-2.0
19 | #
20 |
21 | ##############################################################################
22 | #
23 | # Gradle start up script for POSIX generated by Gradle.
24 | #
25 | # Important for running:
26 | #
27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
28 | # noncompliant, but you have some other compliant shell such as ksh or
29 | # bash, then to run this script, type that shell name before the whole
30 | # command line, like:
31 | #
32 | # ksh Gradle
33 | #
34 | # Busybox and similar reduced shells will NOT work, because this script
35 | # requires all of these POSIX shell features:
36 | # * functions;
37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
39 | # * compound commands having a testable exit status, especially «case»;
40 | # * various built-in commands including «command», «set», and «ulimit».
41 | #
42 | # Important for patching:
43 | #
44 | # (2) This script targets any POSIX shell, so it avoids extensions provided
45 | # by Bash, Ksh, etc; in particular arrays are avoided.
46 | #
47 | # The "traditional" practice of packing multiple parameters into a
48 | # space-separated string is a well documented source of bugs and security
49 | # problems, so this is (mostly) avoided, by progressively accumulating
50 | # options in "$@", and eventually passing that to Java.
51 | #
52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
54 | # see the in-line comments for details.
55 | #
56 | # There are tweaks for specific operating systems such as AIX, CygWin,
57 | # Darwin, MinGW, and NonStop.
58 | #
59 | # (3) This script is generated from the Groovy template
60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
61 | # within the Gradle project.
62 | #
63 | # You can find Gradle at https://github.com/gradle/gradle/.
64 | #
65 | ##############################################################################
66 |
67 | # Attempt to set APP_HOME
68 |
69 | # Resolve links: $0 may be a link
70 | app_path=$0
71 |
72 | # Need this for daisy-chained symlinks.
73 | while
74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
75 | [ -h "$app_path" ]
76 | do
77 | ls=$( ls -ld "$app_path" )
78 | link=${ls#*' -> '}
79 | case $link in #(
80 | /*) app_path=$link ;; #(
81 | *) app_path=$APP_HOME$link ;;
82 | esac
83 | done
84 |
85 | # This is normally unused
86 | # shellcheck disable=SC2034
87 | APP_BASE_NAME=${0##*/}
88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH="\\\"\\\""
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | if ! command -v java >/dev/null 2>&1
137 | then
138 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
139 |
140 | Please set the JAVA_HOME variable in your environment to match the
141 | location of your Java installation."
142 | fi
143 | fi
144 |
145 | # Increase the maximum file descriptors if we can.
146 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
147 | case $MAX_FD in #(
148 | max*)
149 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
150 | # shellcheck disable=SC2039,SC3045
151 | MAX_FD=$( ulimit -H -n ) ||
152 | warn "Could not query maximum file descriptor limit"
153 | esac
154 | case $MAX_FD in #(
155 | '' | soft) :;; #(
156 | *)
157 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
158 | # shellcheck disable=SC2039,SC3045
159 | ulimit -n "$MAX_FD" ||
160 | warn "Could not set maximum file descriptor limit to $MAX_FD"
161 | esac
162 | fi
163 |
164 | # Collect all arguments for the java command, stacking in reverse order:
165 | # * args from the command line
166 | # * the main class name
167 | # * -classpath
168 | # * -D...appname settings
169 | # * --module-path (only if needed)
170 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
171 |
172 | # For Cygwin or MSYS, switch paths to Windows format before running java
173 | if "$cygwin" || "$msys" ; then
174 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
175 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
176 |
177 | JAVACMD=$( cygpath --unix "$JAVACMD" )
178 |
179 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
180 | for arg do
181 | if
182 | case $arg in #(
183 | -*) false ;; # don't mess with options #(
184 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
185 | [ -e "$t" ] ;; #(
186 | *) false ;;
187 | esac
188 | then
189 | arg=$( cygpath --path --ignore --mixed "$arg" )
190 | fi
191 | # Roll the args list around exactly as many times as the number of
192 | # args, so each arg winds up back in the position where it started, but
193 | # possibly modified.
194 | #
195 | # NB: a `for` loop captures its iteration list before it begins, so
196 | # changing the positional parameters here affects neither the number of
197 | # iterations, nor the values presented in `arg`.
198 | shift # remove old arg
199 | set -- "$@" "$arg" # push replacement arg
200 | done
201 | fi
202 |
203 |
204 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
205 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
206 |
207 | # Collect all arguments for the java command:
208 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
209 | # and any embedded shellness will be escaped.
210 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
211 | # treated as '${Hostname}' itself on the command line.
212 |
213 | set -- \
214 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
215 | -classpath "$CLASSPATH" \
216 | -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
217 | "$@"
218 |
219 | # Stop when "xargs" is not available.
220 | if ! command -v xargs >/dev/null 2>&1
221 | then
222 | die "xargs is not available"
223 | fi
224 |
225 | # Use "xargs" to parse quoted args.
226 | #
227 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
228 | #
229 | # In Bash we could simply go:
230 | #
231 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
232 | # set -- "${ARGS[@]}" "$@"
233 | #
234 | # but POSIX shell has neither arrays nor command substitution, so instead we
235 | # post-process each arg (as a line of input to sed) to backslash-escape any
236 | # character that might be a shell metacharacter, then use eval to reverse
237 | # that process (while maintaining the separation between arguments), and wrap
238 | # the whole thing up as a single "set" statement.
239 | #
240 | # This will of course break if any of these variables contains a newline or
241 | # an unmatched quote.
242 | #
243 |
244 | eval "set -- $(
245 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
246 | xargs -n1 |
247 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
248 | tr '\n' ' '
249 | )" '"$@"'
250 |
251 | exec "$JAVACMD" "$@"
252 |
--------------------------------------------------------------------------------
/src/test/java/net/juniper/netconf/element/RpcReplyLoadConfigResultsTest.java:
--------------------------------------------------------------------------------
1 | package net.juniper.netconf.element;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.xmlunit.assertj.XmlAssert;
5 |
6 | import static org.assertj.core.api.Assertions.assertThat;
7 |
8 | public class RpcReplyLoadConfigResultsTest {
9 |
10 | private static final String LOAD_CONFIG_RESULTS_OK_NO_NAMESPACE = """
11 | \
12 |