vendor snakeyaml
we can't use shade-maven-plugin directly being incompatible with incremental versionning Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
4d8d3540b0
commit
9d837317eb
|
|
@ -2,7 +2,6 @@ target/
|
|||
work/
|
||||
.idea/
|
||||
*.iml
|
||||
snakeyaml/src
|
||||
|
||||
# ignore jenkins.yaml from root folder (used by many for testing)
|
||||
/jenkins.yaml
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
This is a vendored version of snakeyaml library.
|
||||
|
||||
To upgrade, change `snakeyaml.version` and run `mvn -Pvendor package`
|
||||
|
|
@ -1,538 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>parent</artifactId>
|
||||
<groupId>io.jenkins.configuration-as-code</groupId>
|
||||
<version>${revision}${changelist}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<description>Snakeyaml shaded for configuration-as-code plugin</description>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>shade</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<createSourcesJar>true</createSourcesJar>
|
||||
<shadeSourcesContent>true</shadeSourcesContent>
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<include>org.yaml*:*</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.yaml.snakeyaml</pattern>
|
||||
<shadedPattern>io.jenkins.plugins.casc.snakeyaml</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>unpack</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>unpack</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>${project.artifactId}</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>sources</classifier>
|
||||
<type>jar</type>
|
||||
<outputDirectory>${basedir}/src/main/java</outputDirectory>
|
||||
<includes>**/**</includes>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.jcip</groupId>
|
||||
<artifactId>jcip-annotations</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>animal-sniffer-annotations</artifactId>
|
||||
<version>1.17</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jenkins-ci.main</groupId>
|
||||
<artifactId>jenkins-core</artifactId>
|
||||
<version>2.60.3</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>icon-set</artifactId>
|
||||
<groupId>org.jenkins-ci.plugins.icon-shim</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>remoting</artifactId>
|
||||
<groupId>org.jenkins-ci.main</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>cli</artifactId>
|
||||
<groupId>org.jenkins-ci.main</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>version-number</artifactId>
|
||||
<groupId>org.jenkins-ci</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>crypto-util</artifactId>
|
||||
<groupId>org.jenkins-ci</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jtidy</artifactId>
|
||||
<groupId>org.jvnet.hudson</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>guice</artifactId>
|
||||
<groupId>com.google.inject</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jna-posix</artifactId>
|
||||
<groupId>org.jruby.ext.posix</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jnr-posix</artifactId>
|
||||
<groupId>com.github.jnr</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>trilead-putty-extension</artifactId>
|
||||
<groupId>org.kohsuke</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>trilead-ssh2</artifactId>
|
||||
<groupId>org.jenkins-ci</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>stapler-groovy</artifactId>
|
||||
<groupId>org.kohsuke.stapler</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>stapler-jrebel</artifactId>
|
||||
<groupId>org.kohsuke.stapler</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>windows-package-checker</artifactId>
|
||||
<groupId>org.kohsuke</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>stapler-adjunct-zeroclipboard</artifactId>
|
||||
<groupId>org.kohsuke.stapler</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>stapler-adjunct-timeline</artifactId>
|
||||
<groupId>org.kohsuke.stapler</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>stapler-adjunct-codemirror</artifactId>
|
||||
<groupId>org.kohsuke.stapler</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>bridge-method-annotation</artifactId>
|
||||
<groupId>com.infradna.tool</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>json-lib</artifactId>
|
||||
<groupId>org.kohsuke.stapler</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>commons-httpclient</artifactId>
|
||||
<groupId>commons-httpclient</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>args4j</artifactId>
|
||||
<groupId>args4j</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>annotation-indexer</artifactId>
|
||||
<groupId>org.jenkins-ci</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>bytecode-compatibility-transformer</artifactId>
|
||||
<groupId>org.jenkins-ci</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>task-reactor</artifactId>
|
||||
<groupId>org.jenkins-ci</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>localizer</artifactId>
|
||||
<groupId>org.jvnet.localizer</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>antlr</artifactId>
|
||||
<groupId>antlr</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>xstream</artifactId>
|
||||
<groupId>org.jvnet.hudson</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jfreechart</artifactId>
|
||||
<groupId>jfree</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>ant</artifactId>
|
||||
<groupId>org.apache.ant</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<groupId>commons-io</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<groupId>commons-lang</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>commons-digester</artifactId>
|
||||
<groupId>commons-digester</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>mail</artifactId>
|
||||
<groupId>javax.mail</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>activation</artifactId>
|
||||
<groupId>org.jvnet.hudson</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jaxen</artifactId>
|
||||
<groupId>jaxen</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>commons-jelly-tags-fmt</artifactId>
|
||||
<groupId>commons-jelly</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>commons-jelly-tags-xml</artifactId>
|
||||
<groupId>commons-jelly</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>commons-jelly-tags-define</artifactId>
|
||||
<groupId>org.jvnet.hudson</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>commons-jexl</artifactId>
|
||||
<groupId>org.jenkins-ci</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>acegi-security</artifactId>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>groovy-all</artifactId>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jline</artifactId>
|
||||
<groupId>jline</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jansi</artifactId>
|
||||
<groupId>org.fusesource.jansi</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<groupId>org.springframework</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<groupId>org.springframework</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<groupId>org.springframework</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>xpp3</artifactId>
|
||||
<groupId>xpp3</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jstl</artifactId>
|
||||
<groupId>javax.servlet</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>txw2</artifactId>
|
||||
<groupId>com.sun.xml.txw2</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>commons-collections</artifactId>
|
||||
<groupId>commons-collections</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>winp</artifactId>
|
||||
<groupId>org.jvnet.winp</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>memory-monitor</artifactId>
|
||||
<groupId>org.jenkins-ci</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>wstx-asl</artifactId>
|
||||
<groupId>org.codehaus.woodstox</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jmdns</artifactId>
|
||||
<groupId>org.jenkins-ci</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jna</artifactId>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>akuma</artifactId>
|
||||
<groupId>org.kohsuke</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>libpam4j</artifactId>
|
||||
<groupId>org.kohsuke</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>libzfs</artifactId>
|
||||
<groupId>org.kohsuke</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>embedded_su4j</artifactId>
|
||||
<groupId>com.sun.solaris</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>sezpoz</artifactId>
|
||||
<groupId>net.java.sezpoz</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>j-interop</artifactId>
|
||||
<groupId>org.kohsuke.jinterop</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>robust-http-client</artifactId>
|
||||
<groupId>org.jvnet.robust-http-client</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>symbol-annotation</artifactId>
|
||||
<groupId>org.jenkins-ci</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<groupId>commons-codec</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>guava</artifactId>
|
||||
<groupId>com.google.guava</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jzlib</artifactId>
|
||||
<groupId>com.jcraft</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jenkins-ci.main</groupId>
|
||||
<artifactId>jenkins-war</artifactId>
|
||||
<version>2.60.3</version>
|
||||
<type>executable-war</type>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>instance-identity</artifactId>
|
||||
<groupId>org.jenkins-ci.modules</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>ssh-cli-auth</artifactId>
|
||||
<groupId>org.jenkins-ci.modules</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>slave-installer</artifactId>
|
||||
<groupId>org.jenkins-ci.modules</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>windows-slave-installer</artifactId>
|
||||
<groupId>org.jenkins-ci.modules</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>launchd-slave-installer</artifactId>
|
||||
<groupId>org.jenkins-ci.modules</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>upstart-slave-installer</artifactId>
|
||||
<groupId>org.jenkins-ci.modules</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>systemd-slave-installer</artifactId>
|
||||
<groupId>org.jenkins-ci.modules</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>sshd</artifactId>
|
||||
<groupId>org.jenkins-ci.modules</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jquery-detached</artifactId>
|
||||
<groupId>org.jenkins-ci.ui</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>bootstrap</artifactId>
|
||||
<groupId>org.jenkins-ci.ui</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>handlebars</artifactId>
|
||||
<groupId>org.jenkins-ci.ui</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>remoting</artifactId>
|
||||
<groupId>org.jenkins-ci.main</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jenkins-ci.main</groupId>
|
||||
<artifactId>jenkins-test-harness</artifactId>
|
||||
<version>2.38</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>junit-dep</artifactId>
|
||||
<groupId>junit</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jetty-security</artifactId>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>hamcrest-library</artifactId>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jenkins-test-harness-htmlunit</artifactId>
|
||||
<groupId>org.jenkins-ci.main</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>embedded-rhino-debugger</artifactId>
|
||||
<groupId>org.jvnet.hudson</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>org-netbeans-insane</artifactId>
|
||||
<groupId>org.netbeans.modules</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>findbugs-annotations</artifactId>
|
||||
<groupId>com.github.stephenc.findbugs</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jenkins-ci</groupId>
|
||||
<artifactId>test-annotations</artifactId>
|
||||
<version>1.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>hamcrest-core</artifactId>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.25</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>log4j-over-slf4j</artifactId>
|
||||
<version>1.7.25</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<version>1.7.25</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-jdk14</artifactId>
|
||||
<version>1.7.25</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.kohsuke</groupId>
|
||||
<artifactId>access-modifier-annotation</artifactId>
|
||||
<version>1.15</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>annotation-indexer</artifactId>
|
||||
<groupId>org.jenkins-ci</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<properties>
|
||||
<findbugs.skip>true</findbugs.skip>
|
||||
<maven.source.skip>true</maven.source.skip>
|
||||
</properties>
|
||||
</project>
|
||||
|
||||
|
|
@ -11,76 +11,92 @@
|
|||
<description>Snakeyaml shaded for configuration-as-code plugin</description>
|
||||
|
||||
<properties>
|
||||
<maven.source.skip>true</maven.source.skip>
|
||||
<findbugs.skip>true</findbugs.skip>
|
||||
<maven.javadoc.skip>true</maven.javadoc.skip>
|
||||
<snakeyaml.version>1.23</snakeyaml.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>1.23</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>vendor</id>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>shade</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<createSourcesJar>true</createSourcesJar>
|
||||
<shadeSourcesContent>true</shadeSourcesContent>
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<include>org.yaml*:*</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.yaml.snakeyaml</pattern>
|
||||
<shadedPattern>io.jenkins.plugins.casc.snakeyaml</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>unpack</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>unpack</goal>
|
||||
</goals>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>${snakeyaml.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>${project.artifactId}</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>sources</classifier>
|
||||
<type>jar</type>
|
||||
<outputDirectory>${basedir}/src/main/java</outputDirectory>
|
||||
<includes>**/**</includes>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
<directory>${basedir}/src</directory>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>shade</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<createSourcesJar>true</createSourcesJar>
|
||||
<shadeSourcesContent>true</shadeSourcesContent>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<include>org.yaml*:*</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.yaml.snakeyaml</pattern>
|
||||
<shadedPattern>io.jenkins.plugins.casc.snakeyaml</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>unpack</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>unpack</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>${project.artifactId}</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>sources</classifier>
|
||||
<type>jar</type>
|
||||
<outputDirectory>${basedir}/src/main/java</outputDirectory>
|
||||
<includes>**/**</includes>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
|
||||
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
Manifest-Version: 1.0
|
||||
Built-By: somov
|
||||
Created-By: Apache Maven 3.5.3
|
||||
Build-Jdk: 1.8.0_181
|
||||
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
#Created by Apache Maven 3.5.3
|
||||
version=1.23
|
||||
groupId=org.yaml
|
||||
artifactId=snakeyaml
|
||||
|
|
@ -0,0 +1,833 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>1.23</version>
|
||||
<packaging>bundle</packaging>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.scm.id>bitbucket</project.scm.id>
|
||||
<release.repo.url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</release.repo.url>
|
||||
<snapshot.repo.url>https://oss.sonatype.org/content/repositories/snapshots/</snapshot.repo.url>
|
||||
<maven.compiler.source>1.6</maven.compiler.source>
|
||||
<maven.compiler.target>1.6</maven.compiler.target>
|
||||
<maven.javadoc.failOnError>false</maven.javadoc.failOnError>
|
||||
<spring.version>3.2.17.RELEASE</spring.version>
|
||||
<maven-bundle-plugin.version>3.5.0</maven-bundle-plugin.version>
|
||||
<cobertura-maven-plugin.version>2.7</cobertura-maven-plugin.version>
|
||||
<maven-site-plugin.version>3.6</maven-site-plugin.version>
|
||||
<maven-surefire-plugin.version>2.19.1</maven-surefire-plugin.version>
|
||||
<jdk9-illegal-access-level>deny</jdk9-illegal-access-level>
|
||||
</properties>
|
||||
<name>SnakeYAML</name>
|
||||
<description>YAML 1.1 parser and emitter for Java</description>
|
||||
<inceptionYear>2008</inceptionYear>
|
||||
<url>http://www.snakeyaml.org</url>
|
||||
<issueManagement>
|
||||
<system>Bitbucket</system>
|
||||
<url>https://bitbucket.org/asomov/snakeyaml/issues</url>
|
||||
</issueManagement>
|
||||
<!--ciManagement>
|
||||
<system>jenkins</system>
|
||||
<url>https://snakeyaml.ci.cloudbees.com/job/SnakeYAML/</url>
|
||||
</ciManagement-->
|
||||
<mailingLists>
|
||||
<mailingList>
|
||||
<name>SnakeYAML developers and users List</name>
|
||||
<post>snakeyaml-core@googlegroups.com</post>
|
||||
</mailingList>
|
||||
</mailingLists>
|
||||
<scm>
|
||||
<connection>scm:hg:http://bitbucket.org/asomov/snakeyaml</connection>
|
||||
<developerConnection>scm:hg:ssh://hg@bitbucket.org/asomov/snakeyaml</developerConnection>
|
||||
<url>https://bitbucket.org/asomov/snakeyaml/src</url>
|
||||
<tag>snakeyaml-1.23</tag>
|
||||
</scm>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>asomov</id>
|
||||
<name>Andrey Somov</name>
|
||||
<email>public.somov@gmail.com</email>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>maslovalex</id>
|
||||
<name>Alexander Maslov</name>
|
||||
<email>alexander.maslov@gmail.com</email>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>Jordan</id>
|
||||
<name>Jordan Angold</name>
|
||||
<email>jordanangold@gmail.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
<artifactId>velocity</artifactId>
|
||||
<version>1.6.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
<version>1.6</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>sonatype-nexus-staging</id>
|
||||
<name>Nexus Release Repository</name>
|
||||
<url>${release.repo.url}</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>sonatype-nexus-staging</id>
|
||||
<name>Sonatype Nexus Snapshots</name>
|
||||
<url>${snapshot.repo.url}</url>
|
||||
<uniqueVersion>false</uniqueVersion>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
<build>
|
||||
<testResources>
|
||||
<testResource>
|
||||
<directory>${basedir}/src/test/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</testResource>
|
||||
</testResources>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.10.4</version>
|
||||
<configuration>
|
||||
<excludePackageNames>org.yaml.snakeyaml.external.*</excludePackageNames>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<version>${maven-site-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>cobertura-maven-plugin</artifactId>
|
||||
<version>${cobertura-maven-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<version>1.12</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven-surefire-plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
<version>1.4.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>enforce-maven</id>
|
||||
<goals>
|
||||
<goal>enforce</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<rules>
|
||||
<requireMavenVersion>
|
||||
<version>3.0.5</version>
|
||||
</requireMavenVersion>
|
||||
</rules>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
<encoding>${project.build.sourceEncoding}</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>-Xmx512m</argLine>
|
||||
<includes>
|
||||
<include>**/*Test.java</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>**/StressTest.java</exclude>
|
||||
<exclude>**/ParallelTest.java</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-eclipse-plugin</artifactId>
|
||||
<version>2.10</version>
|
||||
<configuration>
|
||||
<buildOutputDirectory>bin</buildOutputDirectory>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-changes-plugin</artifactId>
|
||||
<version>2.12.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>validate-changes</id>
|
||||
<phase>pre-site</phase>
|
||||
<goals>
|
||||
<goal>changes-validate</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<failOnError>true</failOnError>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>jar-no-fork</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<configuration>
|
||||
<links>
|
||||
<link>https://docs.oracle.com/javase/6/docs/api/</link>
|
||||
</links>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.mycila.maven-license-plugin</groupId>
|
||||
<artifactId>maven-license-plugin</artifactId>
|
||||
<version>1.10.b1</version>
|
||||
<configuration>
|
||||
<header>src/etc/header.txt</header>
|
||||
<quiet>false</quiet>
|
||||
<failIfMissing>true</failIfMissing>
|
||||
<aggregate>false</aggregate>
|
||||
<includes>
|
||||
<include>src/**/*.java</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>src/main/java/org/yaml/snakeyaml/external/**</exclude>
|
||||
</excludes>
|
||||
<useDefaultExcludes>true</useDefaultExcludes>
|
||||
<useDefaultMapping>true</useDefaultMapping>
|
||||
<strictCheck>true</strictCheck>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>site</phase>
|
||||
<goals>
|
||||
<goal>format</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<version>${maven-bundle-plugin.version}</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<_nouses>true</_nouses>
|
||||
<Export-Package>
|
||||
!org.yaml.snakeyaml.external*,
|
||||
org.yaml.snakeyaml.*;version=${project.version}
|
||||
</Export-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<version>${maven-site-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-descriptor</id>
|
||||
<goals>
|
||||
<goal>attach-descriptor</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>2.5.3</version>
|
||||
<configuration>
|
||||
<autoVersionSubmodules>true</autoVersionSubmodules>
|
||||
<useReleaseProfile>false</useReleaseProfile>
|
||||
<releaseProfiles>android,release</releaseProfiles>
|
||||
<goals>deploy nexus-staging:release</goals>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.sonatype.plugins</groupId>
|
||||
<artifactId>nexus-staging-maven-plugin</artifactId>
|
||||
<version>1.6.7</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<serverId>sonatype-nexus-staging</serverId>
|
||||
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
|
||||
<autoReleaseAfterClose>false</autoReleaseAfterClose>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-changes-plugin</artifactId>
|
||||
<version>2.11</version>
|
||||
<configuration>
|
||||
<issueLinkTemplate>https://bitbucket.org/asomov/snakeyaml/issues/%ISSUE%</issueLinkTemplate>
|
||||
</configuration>
|
||||
<reportSets>
|
||||
<reportSet>
|
||||
<reports>
|
||||
<report>changes-report</report>
|
||||
</reports>
|
||||
</reportSet>
|
||||
</reportSets>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-report-plugin</artifactId>
|
||||
<version>${maven-surefire-plugin.version}</version>
|
||||
<configuration>
|
||||
<showSuccess>true</showSuccess>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<reportSets>
|
||||
<reportSet>
|
||||
<id>html</id>
|
||||
<configuration>
|
||||
<doctitle>API for ${project.name} ${project.version}</doctitle>
|
||||
<windowtitle>API for ${project.name} ${project.version}</windowtitle>
|
||||
<testDoctitle>Test API for ${project.name} ${project.version}</testDoctitle>
|
||||
<testWindowtitle>Test API for ${project.name} ${project.version}</testWindowtitle>
|
||||
</configuration>
|
||||
<reports>
|
||||
<report>javadoc</report>
|
||||
</reports>
|
||||
</reportSet>
|
||||
</reportSets>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>toolchain</id>
|
||||
<activation>
|
||||
<file>
|
||||
<exists>${user.home}/.m2/toolchains.xml</exists>
|
||||
</file>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-toolchains-plugin</artifactId>
|
||||
<version>1.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>validate</phase>
|
||||
<goals>
|
||||
<goal>toolchain</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<toolchains>
|
||||
<jdk>
|
||||
<version>${maven.compiler.target}</version>
|
||||
</jdk>
|
||||
</toolchains>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>build-is-under-jdk6</id>
|
||||
<activation>
|
||||
<jdk>1.6</jdk>
|
||||
</activation>
|
||||
<properties>
|
||||
<maven-bundle-plugin.version>2.5.4</maven-bundle-plugin.version>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>with-coverage</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>cobertura-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<check>
|
||||
<totalBranchRate>80</totalBranchRate>
|
||||
<totalLineRate>95</totalLineRate>
|
||||
</check>
|
||||
<formats>
|
||||
<format>html</format>
|
||||
<format>xml</format>
|
||||
</formats>
|
||||
<instrumentation>
|
||||
<excludes>
|
||||
<exclude>org/yaml/snakeyaml/external/**</exclude>
|
||||
</excludes>
|
||||
</instrumentation>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>clean</goal>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>cobertura-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<check>
|
||||
<branchRate>85</branchRate>
|
||||
<lineRate>85</lineRate>
|
||||
<haltOnFailure>true</haltOnFailure>
|
||||
</check>
|
||||
<formats>
|
||||
<format>html</format>
|
||||
<format>xml</format>
|
||||
</formats>
|
||||
</configuration>
|
||||
<reportSets>
|
||||
<reportSet>
|
||||
<reports>
|
||||
<report>cobertura</report>
|
||||
</reports>
|
||||
</reportSet>
|
||||
</reportSets>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>with-java8-tests</id>
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>add-java8-test-source</id>
|
||||
<phase>generate-test-sources</phase>
|
||||
<goals>
|
||||
<goal>add-test-source</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sources>
|
||||
<source>${basedir}/src/test/java7/</source>
|
||||
<source>${basedir}/src/test/java8/</source>
|
||||
</sources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>with-java11-tests</id>
|
||||
<properties>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>--illegal-access=${jdk9-illegal-access-level} -Xmx512m</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<compilerArgs>
|
||||
<!-- arg>-Xlint:unchecked</arg -->
|
||||
<arg>-Xlint:deprecation</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>add-java11-test-source</id>
|
||||
<phase>generate-test-sources</phase>
|
||||
<goals>
|
||||
<goal>add-test-source</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sources>
|
||||
<source>${basedir}/src/test/java7/</source>
|
||||
<source>${basedir}/src/test/java8/</source>
|
||||
<source>${basedir}/src/test/java11/</source>
|
||||
</sources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>release</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>performRelease</name>
|
||||
<value>true</value>
|
||||
</property>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>1.6</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>findbugs</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>findbugs-maven-plugin</artifactId>
|
||||
<version>3.0.4</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-pmd-plugin</artifactId>
|
||||
<version>3.7</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jxr-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>findbugs-maven-plugin</artifactId>
|
||||
<version>3.0.4</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-pmd-plugin</artifactId>
|
||||
<version>3.6</version>
|
||||
<configuration>
|
||||
<linkXref>true</linkXref>
|
||||
<sourceEncoding>utf-8</sourceEncoding>
|
||||
<minimumTokens>100</minimumTokens>
|
||||
<targetJdk>1.5</targetJdk>
|
||||
<excludes>
|
||||
<exclude>**/external/*.java</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>android</id>
|
||||
<properties>
|
||||
<android.src>${project.build.directory}/android/src</android.src>
|
||||
<android.src.main>${android.src}/main/java</android.src.main>
|
||||
<android.src.test>${android.src}/test/java</android.src.test>
|
||||
<android.classes>${project.build.directory}/android/classes/</android.classes>
|
||||
<android.test.classes>${project.build.directory}/android/test-classes/</android.test.classes>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-src-for-android</id>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${android.src.main}</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${basedir}/src/main/java</directory>
|
||||
<filtering>false</filtering>
|
||||
<excludes>
|
||||
<exclude>org/yaml/snakeyaml/introspector/MethodProperty.java</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-test-src-for-android</id>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${android.src.test}</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${basedir}/src/test/java</directory>
|
||||
<filtering>false</filtering>
|
||||
<excludes>
|
||||
<exclude>org/yaml/snakeyaml/introspector/MethodProperty.java</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-test-resources-for-android</id>
|
||||
<phase>process-test-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${android.test.classes}</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${basedir}/src/test/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-patch-plugin</artifactId>
|
||||
<version>1.2</version>
|
||||
<configuration>
|
||||
<patchDirectory>${basedir}/src/patches/android/</patchDirectory>
|
||||
<targetDirectory>${android.src}</targetDirectory>
|
||||
<skipApplication>false</skipApplication>
|
||||
<strip>2</strip>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>android-patches</id>
|
||||
<phase>process-sources</phase>
|
||||
<goals>
|
||||
<goal>apply</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<patchTrackingFile>${project.build.directory}/android/patches-applied.txt</patchTrackingFile>
|
||||
<naturalOrderProcessing>true</naturalOrderProcessing>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<version>1.8</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>build-for-android</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<target>
|
||||
<mkdir dir="${android.classes}" />
|
||||
<mkdir dir="${android.test.classes}" />
|
||||
|
||||
<!-- compile patched sources -->
|
||||
<javac srcdir="${android.src.main}" destdir="${android.classes}" classpath="${android.classes}" encoding="${project.build.sourceEncoding}" target="1.6" source="1.6" debug="true" includeantruntime="false" fork="true" />
|
||||
|
||||
<!-- compile test classes. Exclude some - not for BeanAccess.FIELD -->
|
||||
<javac srcdir="${android.src.test}:${basedir}/src/test/resources" destdir="${android.test.classes}" classpath="${android.classes}:${android.test.classes}:${junit:junit:jar}:${org.springframework:spring-core:jar}:${org.springframework:spring-beans:jar}:${org.springframework:spring-context:jar}:${org.apache.velocity:velocity:jar}:${joda-time:joda-time:jar}:${commons-io:commons-io:jar}:${commons-lang:commons-lang:jar}:${org.hamcrest:hamcrest-core:jar}" encoding="${project.build.sourceEncoding}" target="1.6" source="1.6" debug="true" includeantruntime="false" fork="true">
|
||||
|
||||
<exclude name="org/yaml/snakeyaml/introspector/MethodPropertyTest.java" />
|
||||
<exclude name="org/yaml/snakeyaml/representer/FilterPropertyToDumpTest.java" />
|
||||
<exclude name="org/yaml/snakeyaml/issues/issue60/CustomOrderTest.java" />
|
||||
<exclude name="org/yaml/snakeyaml/issues/issue29/FlexibleScalarStylesInJavaBeanTest.java" />
|
||||
<!-- uses filtered resources. Addidional tricks needed to be able to run under current build -->
|
||||
<exclude name="org/yaml/snakeyaml/issues/issue318/ContextClassLoaderTest.java" />
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>test-android</id>
|
||||
<phase>test</phase>
|
||||
<goals>
|
||||
<goal>test</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<classesDirectory>${android.classes}</classesDirectory>
|
||||
<reportsDirectory>${project.build.directory}/android/surefire-reports
|
||||
</reportsDirectory>
|
||||
<testClassesDirectory>${android.test.classes}</testClassesDirectory>
|
||||
<!--
|
||||
We ignore test failures for android build at the moment.
|
||||
Most of the FAILs are because of testing with "property" not "field" access.
|
||||
But we still fail whole build if there are test errors.
|
||||
-->
|
||||
<testFailureIgnore>true</testFailureIgnore>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>package-android-jar</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<classesDirectory>${android.classes}</classesDirectory>
|
||||
<classifier>android</classifier>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,418 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.emitter.Emitter;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.YAMLException;
|
||||
import io.jenkins.plugins.casc.snakeyaml.serializer.AnchorGenerator;
|
||||
import io.jenkins.plugins.casc.snakeyaml.serializer.NumberAnchorGenerator;
|
||||
|
||||
public class DumperOptions {
|
||||
/**
|
||||
* YAML provides a rich set of scalar styles. Block scalar styles include
|
||||
* the literal style and the folded style; flow scalar styles include the
|
||||
* plain style and two quoted styles, the single-quoted style and the
|
||||
* double-quoted style. These styles offer a range of trade-offs between
|
||||
* expressive power and readability.
|
||||
*
|
||||
* @see <a href="http://yaml.org/spec/1.1/#id903915">Chapter 9. Scalar
|
||||
* Styles</a>
|
||||
* @see <a href="http://yaml.org/spec/1.1/#id858081">2.3. Scalars</a>
|
||||
*/
|
||||
public enum ScalarStyle {
|
||||
DOUBLE_QUOTED('"'), SINGLE_QUOTED('\''), LITERAL(
|
||||
'|'), FOLDED('>'), PLAIN(null);
|
||||
private Character styleChar;
|
||||
|
||||
private ScalarStyle(Character style) {
|
||||
this.styleChar = style;
|
||||
}
|
||||
|
||||
public Character getChar() {
|
||||
return styleChar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Scalar style: '" + styleChar + "'";
|
||||
}
|
||||
|
||||
public static ScalarStyle createStyle(Character style) {
|
||||
if (style == null) {
|
||||
return PLAIN;
|
||||
} else {
|
||||
switch (style) {
|
||||
case '"':
|
||||
return DOUBLE_QUOTED;
|
||||
case '\'':
|
||||
return SINGLE_QUOTED;
|
||||
case '|':
|
||||
return LITERAL;
|
||||
case '>':
|
||||
return FOLDED;
|
||||
default:
|
||||
throw new YAMLException("Unknown scalar style character: " + style);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Block styles use indentation to denote nesting and scope within the
|
||||
* document. In contrast, flow styles rely on explicit indicators to denote
|
||||
* nesting and scope.
|
||||
*
|
||||
* @see <a href="http://www.yaml.org/spec/current.html#id2509255">3.2.3.1.
|
||||
* Node Styles (http://yaml.org/spec/1.1)</a>
|
||||
*/
|
||||
public enum FlowStyle {
|
||||
FLOW(Boolean.TRUE), BLOCK(Boolean.FALSE), AUTO(null);
|
||||
|
||||
private Boolean styleBoolean;
|
||||
|
||||
private FlowStyle(Boolean flowStyle) {
|
||||
styleBoolean = flowStyle;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convenience for legacy constructors that took {@link Boolean} arguments since replaced by {@link FlowStyle}.
|
||||
* Introduced in v1.22 but only to support that for backwards compatibility.
|
||||
* @deprecated Since restored in v1.22. Use the {@link FlowStyle} constants in your code instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static FlowStyle fromBoolean(Boolean flowStyle) {
|
||||
return flowStyle==null ? AUTO
|
||||
: flowStyle ? FLOW
|
||||
: BLOCK;
|
||||
}
|
||||
|
||||
public Boolean getStyleBoolean() {
|
||||
return styleBoolean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Flow style: '" + styleBoolean + "'";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Platform dependent line break.
|
||||
*/
|
||||
public enum LineBreak {
|
||||
WIN("\r\n"), MAC("\r"), UNIX("\n");
|
||||
|
||||
private String lineBreak;
|
||||
|
||||
private LineBreak(String lineBreak) {
|
||||
this.lineBreak = lineBreak;
|
||||
}
|
||||
|
||||
public String getString() {
|
||||
return lineBreak;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Line break: " + name();
|
||||
}
|
||||
|
||||
public static LineBreak getPlatformLineBreak() {
|
||||
String platformLineBreak = System.getProperty("line.separator");
|
||||
for (LineBreak lb : values()) {
|
||||
if (lb.lineBreak.equals(platformLineBreak)) {
|
||||
return lb;
|
||||
}
|
||||
}
|
||||
return LineBreak.UNIX;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specification version. Currently supported 1.0 and 1.1
|
||||
*/
|
||||
public enum Version {
|
||||
V1_0(new Integer[] { 1, 0 }), V1_1(new Integer[] { 1, 1 });
|
||||
|
||||
private Integer[] version;
|
||||
|
||||
private Version(Integer[] version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public int major() { return version[0]; }
|
||||
public int minor() { return version[1]; }
|
||||
|
||||
public String getRepresentation() {
|
||||
return version[0] + "." + version[1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Version: " + getRepresentation();
|
||||
}
|
||||
}
|
||||
|
||||
private ScalarStyle defaultStyle = ScalarStyle.PLAIN;
|
||||
private FlowStyle defaultFlowStyle = FlowStyle.AUTO;
|
||||
private boolean canonical = false;
|
||||
private boolean allowUnicode = true;
|
||||
private boolean allowReadOnlyProperties = false;
|
||||
private int indent = 2;
|
||||
private int indicatorIndent = 0;
|
||||
private int bestWidth = 80;
|
||||
private boolean splitLines = true;
|
||||
private LineBreak lineBreak = LineBreak.UNIX;
|
||||
private boolean explicitStart = false;
|
||||
private boolean explicitEnd = false;
|
||||
private TimeZone timeZone = null;
|
||||
|
||||
private Version version = null;
|
||||
private Map<String, String> tags = null;
|
||||
private Boolean prettyFlow = false;
|
||||
private AnchorGenerator anchorGenerator = new NumberAnchorGenerator(0);
|
||||
|
||||
public boolean isAllowUnicode() {
|
||||
return allowUnicode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether to emit non-ASCII printable Unicode characters.
|
||||
* The default value is true.
|
||||
* When set to false then printable non-ASCII characters (Cyrillic, Chinese etc)
|
||||
* will be not printed but escaped (to support ASCII terminals)
|
||||
*
|
||||
* @param allowUnicode
|
||||
* if allowUnicode is false then all non-ASCII characters are
|
||||
* escaped
|
||||
*/
|
||||
public void setAllowUnicode(boolean allowUnicode) {
|
||||
this.allowUnicode = allowUnicode;
|
||||
}
|
||||
|
||||
public ScalarStyle getDefaultScalarStyle() {
|
||||
return defaultStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default style for scalars. See YAML 1.1 specification, 2.3 Scalars
|
||||
* (http://yaml.org/spec/1.1/#id858081)
|
||||
*
|
||||
* @param defaultStyle
|
||||
* set the style for all scalars
|
||||
*/
|
||||
public void setDefaultScalarStyle(ScalarStyle defaultStyle) {
|
||||
if (defaultStyle == null) {
|
||||
throw new NullPointerException("Use ScalarStyle enum.");
|
||||
}
|
||||
this.defaultStyle = defaultStyle;
|
||||
}
|
||||
|
||||
public void setIndent(int indent) {
|
||||
if (indent < Emitter.MIN_INDENT) {
|
||||
throw new YAMLException("Indent must be at least " + Emitter.MIN_INDENT);
|
||||
}
|
||||
if (indent > Emitter.MAX_INDENT) {
|
||||
throw new YAMLException("Indent must be at most " + Emitter.MAX_INDENT);
|
||||
}
|
||||
this.indent = indent;
|
||||
}
|
||||
|
||||
public int getIndent() {
|
||||
return this.indent;
|
||||
}
|
||||
|
||||
public void setIndicatorIndent(int indicatorIndent) {
|
||||
if (indicatorIndent < 0) {
|
||||
throw new YAMLException("Indicator indent must be non-negative.");
|
||||
}
|
||||
if (indicatorIndent > Emitter.MAX_INDENT - 1) {
|
||||
throw new YAMLException("Indicator indent must be at most Emitter.MAX_INDENT-1: " + (Emitter.MAX_INDENT - 1));
|
||||
}
|
||||
this.indicatorIndent = indicatorIndent;
|
||||
}
|
||||
|
||||
public int getIndicatorIndent() {
|
||||
return this.indicatorIndent;
|
||||
}
|
||||
|
||||
public void setVersion(Version version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public Version getVersion() {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the emitter to produce a canonical YAML document.
|
||||
*
|
||||
* @param canonical
|
||||
* true produce canonical YAML document
|
||||
*/
|
||||
public void setCanonical(boolean canonical) {
|
||||
this.canonical = canonical;
|
||||
}
|
||||
|
||||
public boolean isCanonical() {
|
||||
return this.canonical;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the emitter to produce a pretty YAML document when using the flow
|
||||
* style.
|
||||
*
|
||||
* @param prettyFlow
|
||||
* true produce pretty flow YAML document
|
||||
*/
|
||||
public void setPrettyFlow(boolean prettyFlow) {
|
||||
this.prettyFlow = prettyFlow;
|
||||
}
|
||||
|
||||
public boolean isPrettyFlow() {
|
||||
return this.prettyFlow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the preferred width to emit scalars. When the scalar
|
||||
* representation takes more then the preferred with the scalar will be
|
||||
* split into a few lines. The default is 80.
|
||||
*
|
||||
* @param bestWidth
|
||||
* the preferred width for scalars.
|
||||
*/
|
||||
public void setWidth(int bestWidth) {
|
||||
this.bestWidth = bestWidth;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return this.bestWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether to split lines exceeding preferred width for
|
||||
* scalars. The default is true.
|
||||
*
|
||||
* @param splitLines
|
||||
* whether to split lines exceeding preferred width for scalars.
|
||||
*/
|
||||
public void setSplitLines(boolean splitLines) {
|
||||
this.splitLines = splitLines;
|
||||
}
|
||||
|
||||
public boolean getSplitLines() {
|
||||
return this.splitLines;
|
||||
}
|
||||
|
||||
public LineBreak getLineBreak() {
|
||||
return lineBreak;
|
||||
}
|
||||
|
||||
public void setDefaultFlowStyle(FlowStyle defaultFlowStyle) {
|
||||
if (defaultFlowStyle == null) {
|
||||
throw new NullPointerException("Use FlowStyle enum.");
|
||||
}
|
||||
this.defaultFlowStyle = defaultFlowStyle;
|
||||
}
|
||||
|
||||
public FlowStyle getDefaultFlowStyle() {
|
||||
return defaultFlowStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the line break to separate the lines. It is platform specific:
|
||||
* Windows - "\r\n", old MacOS - "\r", Unix - "\n". The default value is the
|
||||
* one for Unix.
|
||||
* @param lineBreak to be used for the input
|
||||
*/
|
||||
public void setLineBreak(LineBreak lineBreak) {
|
||||
if (lineBreak == null) {
|
||||
throw new NullPointerException("Specify line break.");
|
||||
}
|
||||
this.lineBreak = lineBreak;
|
||||
}
|
||||
|
||||
public boolean isExplicitStart() {
|
||||
return explicitStart;
|
||||
}
|
||||
|
||||
public void setExplicitStart(boolean explicitStart) {
|
||||
this.explicitStart = explicitStart;
|
||||
}
|
||||
|
||||
public boolean isExplicitEnd() {
|
||||
return explicitEnd;
|
||||
}
|
||||
|
||||
public void setExplicitEnd(boolean explicitEnd) {
|
||||
this.explicitEnd = explicitEnd;
|
||||
}
|
||||
|
||||
public Map<String, String> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
public void setTags(Map<String, String> tags) {
|
||||
this.tags = tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report whether read-only JavaBean properties (the ones without setters)
|
||||
* should be included in the YAML document
|
||||
*
|
||||
* @return false when read-only JavaBean properties are not emitted
|
||||
*/
|
||||
public boolean isAllowReadOnlyProperties() {
|
||||
return allowReadOnlyProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true to include read-only JavaBean properties (the ones without
|
||||
* setters) in the YAML document. By default these properties are not
|
||||
* included to be able to parse later the same JavaBean.
|
||||
*
|
||||
* @param allowReadOnlyProperties
|
||||
* - true to dump read-only JavaBean properties
|
||||
*/
|
||||
public void setAllowReadOnlyProperties(boolean allowReadOnlyProperties) {
|
||||
this.allowReadOnlyProperties = allowReadOnlyProperties;
|
||||
}
|
||||
|
||||
public TimeZone getTimeZone() {
|
||||
return timeZone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the timezone to be used for Date. If set to <code>null</code> UTC is
|
||||
* used.
|
||||
* @param timeZone for created Dates or null to use UTC
|
||||
*/
|
||||
public void setTimeZone(TimeZone timeZone) {
|
||||
this.timeZone = timeZone;
|
||||
}
|
||||
|
||||
|
||||
public AnchorGenerator getAnchorGenerator() {
|
||||
return anchorGenerator;
|
||||
}
|
||||
|
||||
public void setAnchorGenerator(AnchorGenerator anchorGenerator) {
|
||||
this.anchorGenerator = anchorGenerator;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml;
|
||||
|
||||
public class LoaderOptions {
|
||||
|
||||
private boolean allowDuplicateKeys = true;
|
||||
|
||||
public boolean isAllowDuplicateKeys() {
|
||||
return allowDuplicateKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow/Reject duplicate map keys in the YAML file.
|
||||
*
|
||||
* Default is to allow.
|
||||
*
|
||||
* YAML 1.1 is slightly vague around duplicate entries in the YAML file. The
|
||||
* best reference is <a href="http://www.yaml.org/spec/1.1/#id862121">
|
||||
* 3.2.1.3. Nodes Comparison</a> where it hints that a duplicate map key is
|
||||
* an error.
|
||||
*
|
||||
* For future reference, YAML spec 1.2 is clear. The keys MUST be unique.
|
||||
* <a href="http://www.yaml.org/spec/1.2/spec.html#id2759572">1.3. Relation
|
||||
* to JSON</a>
|
||||
* @param allowDuplicateKeys false to reject duplicate mapping keys
|
||||
*/
|
||||
public void setAllowDuplicateKeys(boolean allowDuplicateKeys) {
|
||||
this.allowDuplicateKeys = allowDuplicateKeys;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,411 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.YAMLException;
|
||||
import io.jenkins.plugins.casc.snakeyaml.introspector.BeanAccess;
|
||||
import io.jenkins.plugins.casc.snakeyaml.introspector.Property;
|
||||
import io.jenkins.plugins.casc.snakeyaml.introspector.PropertySubstitute;
|
||||
import io.jenkins.plugins.casc.snakeyaml.introspector.PropertyUtils;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Node;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Tag;
|
||||
|
||||
/**
|
||||
* Provides additional runtime information necessary to create a custom Java
|
||||
* instance.
|
||||
*
|
||||
* In general this class is thread-safe and can be used as a singleton, the only
|
||||
* exception being the PropertyUtils field. A singleton PropertyUtils should be
|
||||
* constructed and shared between all YAML Constructors used if a singleton
|
||||
* TypeDescription is used, since Constructor sets its propertyUtils to the
|
||||
* TypeDescription that is passed to it, hence you may end up in a situation
|
||||
* when propertyUtils in TypeDescription is from different Constructor.
|
||||
*/
|
||||
public class TypeDescription {
|
||||
final private static Logger log = Logger
|
||||
.getLogger(TypeDescription.class.getPackage().getName());
|
||||
|
||||
private final Class<? extends Object> type;
|
||||
|
||||
// class that implements the described type; if set, will be used as a source for constructor.
|
||||
// If not set - TypeDescription will leave instantiation of an entity to the YAML Constructor
|
||||
private Class<?> impl;
|
||||
|
||||
private Tag tag;
|
||||
|
||||
transient private Set<Property> dumpProperties;
|
||||
transient private PropertyUtils propertyUtils;
|
||||
transient private boolean delegatesChecked;
|
||||
|
||||
private Map<String, PropertySubstitute> properties = Collections.emptyMap();
|
||||
|
||||
protected Set<String> excludes = Collections.emptySet();
|
||||
protected String[] includes = null;
|
||||
protected BeanAccess beanAccess;
|
||||
|
||||
public TypeDescription(Class<? extends Object> clazz, Tag tag) {
|
||||
this(clazz, tag, null);
|
||||
}
|
||||
|
||||
public TypeDescription(Class<? extends Object> clazz, Tag tag, Class<?> impl) {
|
||||
this.type = clazz;
|
||||
this.tag = tag;
|
||||
this.impl = impl;
|
||||
beanAccess = null;
|
||||
}
|
||||
|
||||
public TypeDescription(Class<? extends Object> clazz, String tag) {
|
||||
this(clazz, new Tag(tag), null);
|
||||
}
|
||||
|
||||
public TypeDescription(Class<? extends Object> clazz) {
|
||||
this(clazz, (Tag) null, null);
|
||||
}
|
||||
|
||||
public TypeDescription(Class<? extends Object> clazz, Class<?> impl) {
|
||||
this(clazz, null, impl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tag which shall be used to load or dump the type (class).
|
||||
*
|
||||
* @return tag to be used. It may be a tag for Language-Independent Types
|
||||
* (http://www.yaml.org/type/)
|
||||
*/
|
||||
public Tag getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set tag to be used to load or dump the type (class).
|
||||
*
|
||||
* @param tag
|
||||
* local or global tag
|
||||
*/
|
||||
public void setTag(Tag tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
public void setTag(String tag) {
|
||||
setTag(new Tag(tag));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get represented type (class)
|
||||
*
|
||||
* @return type (class) to be described.
|
||||
*/
|
||||
public Class<? extends Object> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that the property is a type-safe <code>List</code>.
|
||||
*
|
||||
* @param property
|
||||
* name of the JavaBean property
|
||||
* @param type
|
||||
* class of List values
|
||||
*/
|
||||
@Deprecated
|
||||
public void putListPropertyType(String property, Class<? extends Object> type) {
|
||||
addPropertyParameters(property, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get class of List values for provided JavaBean property.
|
||||
*
|
||||
* @param property
|
||||
* property name
|
||||
* @return class of List values
|
||||
*/
|
||||
@Deprecated
|
||||
public Class<? extends Object> getListPropertyType(String property) {
|
||||
if (properties.containsKey(property)) {
|
||||
Class<?>[] typeArguments = properties.get(property).getActualTypeArguments();
|
||||
if (typeArguments != null && typeArguments.length > 0) {
|
||||
return typeArguments[0];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that the property is a type-safe <code>Map</code>.
|
||||
*
|
||||
* @param property
|
||||
* property name of this JavaBean
|
||||
* @param key
|
||||
* class of keys in Map
|
||||
* @param value
|
||||
* class of values in Map
|
||||
*/
|
||||
@Deprecated
|
||||
public void putMapPropertyType(String property, Class<? extends Object> key,
|
||||
Class<? extends Object> value) {
|
||||
addPropertyParameters(property, key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get keys type info for this JavaBean
|
||||
*
|
||||
* @param property
|
||||
* property name of this JavaBean
|
||||
* @return class of keys in the Map
|
||||
*/
|
||||
@Deprecated
|
||||
public Class<? extends Object> getMapKeyType(String property) {
|
||||
if (properties.containsKey(property)) {
|
||||
Class<?>[] typeArguments = properties.get(property).getActualTypeArguments();
|
||||
if (typeArguments != null && typeArguments.length > 0) {
|
||||
return typeArguments[0];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get values type info for this JavaBean
|
||||
*
|
||||
* @param property
|
||||
* property name of this JavaBean
|
||||
* @return class of values in the Map
|
||||
*/
|
||||
@Deprecated
|
||||
public Class<? extends Object> getMapValueType(String property) {
|
||||
if (properties.containsKey(property)) {
|
||||
Class<?>[] typeArguments = properties.get(property).getActualTypeArguments();
|
||||
if (typeArguments != null && typeArguments.length > 1) {
|
||||
return typeArguments[1];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new substitute for property <code>pName</code> parameterized by
|
||||
* <code>classes</code> to this <code>TypeDescription</code>. If
|
||||
* <code>pName</code> has been added before - updates parameters with
|
||||
* <code>classes</code>.
|
||||
*
|
||||
* @param pName - parameter name
|
||||
* @param classes - parameterized by
|
||||
*/
|
||||
public void addPropertyParameters(String pName, Class<?>... classes) {
|
||||
if (!properties.containsKey(pName)) {
|
||||
substituteProperty(pName, null, null, null, classes);
|
||||
} else {
|
||||
PropertySubstitute pr = properties.get(pName);
|
||||
pr.setActualTypeArguments(classes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TypeDescription for " + getType() + " (tag='" + getTag() + "')";
|
||||
}
|
||||
|
||||
private void checkDelegates() {
|
||||
Collection<PropertySubstitute> values = properties.values();
|
||||
for (PropertySubstitute p : values) {
|
||||
try {
|
||||
p.setDelegate(discoverProperty(p.getName()));
|
||||
} catch (YAMLException e) {
|
||||
}
|
||||
}
|
||||
delegatesChecked = true;
|
||||
}
|
||||
|
||||
private Property discoverProperty(String name) {
|
||||
if (propertyUtils != null) {
|
||||
if (beanAccess == null) {
|
||||
return propertyUtils.getProperty(type, name);
|
||||
}
|
||||
return propertyUtils.getProperty(type, name, beanAccess);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Property getProperty(String name) {
|
||||
if (!delegatesChecked) {
|
||||
checkDelegates();
|
||||
}
|
||||
return properties.containsKey(name) ? properties.get(name) : discoverProperty(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds property substitute for <code>pName</code>
|
||||
*
|
||||
* @param pName
|
||||
* property name
|
||||
* @param pType
|
||||
* property type
|
||||
* @param getter
|
||||
* method name for getter
|
||||
* @param setter
|
||||
* method name for setter
|
||||
* @param argParams
|
||||
* actual types for parameterized type (List<?>, Map<?>)
|
||||
*/
|
||||
public void substituteProperty(String pName, Class<?> pType, String getter, String setter,
|
||||
Class<?>... argParams) {
|
||||
substituteProperty(new PropertySubstitute(pName, pType, getter, setter, argParams));
|
||||
}
|
||||
|
||||
public void substituteProperty(PropertySubstitute substitute) {
|
||||
if (Collections.EMPTY_MAP == properties) {
|
||||
properties = new LinkedHashMap<String, PropertySubstitute>();
|
||||
}
|
||||
substitute.setTargetType(type);
|
||||
properties.put(substitute.getName(), substitute);
|
||||
}
|
||||
|
||||
public void setPropertyUtils(PropertyUtils propertyUtils) {
|
||||
this.propertyUtils = propertyUtils;
|
||||
}
|
||||
|
||||
/* begin: Representer */
|
||||
public void setIncludes(String... propNames) {
|
||||
this.includes = (propNames != null && propNames.length > 0) ? propNames : null;
|
||||
}
|
||||
|
||||
public void setExcludes(String... propNames) {
|
||||
if (propNames != null && propNames.length > 0) {
|
||||
excludes = new HashSet<String>();
|
||||
for (String name : propNames) {
|
||||
excludes.add(name);
|
||||
}
|
||||
} else {
|
||||
excludes = Collections.emptySet();
|
||||
}
|
||||
}
|
||||
|
||||
public Set<Property> getProperties() {
|
||||
if (dumpProperties != null) {
|
||||
return dumpProperties;
|
||||
}
|
||||
|
||||
if (propertyUtils != null) {
|
||||
if (includes != null) {
|
||||
dumpProperties = new LinkedHashSet<Property>();
|
||||
for (String propertyName : includes) {
|
||||
if (!excludes.contains(propertyName)) {
|
||||
dumpProperties.add(getProperty(propertyName));
|
||||
}
|
||||
}
|
||||
return dumpProperties;
|
||||
}
|
||||
|
||||
final Set<Property> readableProps = (beanAccess == null)
|
||||
? propertyUtils.getProperties(type)
|
||||
: propertyUtils.getProperties(type, beanAccess);
|
||||
|
||||
if (properties.isEmpty()) {
|
||||
if (excludes.isEmpty()) {
|
||||
return dumpProperties = readableProps;
|
||||
}
|
||||
dumpProperties = new LinkedHashSet<Property>();
|
||||
for (Property property : readableProps) {
|
||||
if (!excludes.contains(property.getName())) {
|
||||
dumpProperties.add(property);
|
||||
}
|
||||
}
|
||||
return dumpProperties;
|
||||
}
|
||||
|
||||
if (!delegatesChecked) {
|
||||
checkDelegates();
|
||||
}
|
||||
|
||||
dumpProperties = new LinkedHashSet<Property>();
|
||||
|
||||
for (Property property : properties.values()) {
|
||||
if (!excludes.contains(property.getName()) && property.isReadable()) {
|
||||
dumpProperties.add(property);
|
||||
}
|
||||
}
|
||||
|
||||
for (Property property : readableProps) {
|
||||
if (!excludes.contains(property.getName())) {
|
||||
dumpProperties.add(property);
|
||||
}
|
||||
}
|
||||
|
||||
return dumpProperties;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/* end: Representer */
|
||||
|
||||
/*------------ Maybe something useful to override :) ---------*/
|
||||
|
||||
public boolean setupPropertyType(String key, Node valueNode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean setProperty(Object targetBean, String propertyName, Object value)
|
||||
throws Exception {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should be overridden for TypeDescription implementations that are supposed to implement
|
||||
* instantiation logic that is different from default one as implemented in YAML constructors.
|
||||
* Note that even if you override this method, default filling of fields with
|
||||
* variables from parsed YAML will still occur later.
|
||||
* @param node - node to construct the instance from
|
||||
* @return new instance
|
||||
*/
|
||||
public Object newInstance(Node node) {
|
||||
if (impl != null) {
|
||||
try {
|
||||
java.lang.reflect.Constructor<?> c = impl.getDeclaredConstructor();
|
||||
c.setAccessible(true);
|
||||
return c.newInstance();
|
||||
} catch (Exception e) {
|
||||
log.fine(e.getLocalizedMessage());
|
||||
impl = null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object newInstance(String propertyName, Node node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is invoked after entity is filled with values from deserialized YAML
|
||||
* @param obj - deserialized entity
|
||||
* @return postprocessed deserialized entity
|
||||
*/
|
||||
public Object finalizeConstruction(Object obj) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,749 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.DumperOptions.FlowStyle;
|
||||
import io.jenkins.plugins.casc.snakeyaml.composer.Composer;
|
||||
import io.jenkins.plugins.casc.snakeyaml.constructor.BaseConstructor;
|
||||
import io.jenkins.plugins.casc.snakeyaml.constructor.Constructor;
|
||||
import io.jenkins.plugins.casc.snakeyaml.emitter.Emitable;
|
||||
import io.jenkins.plugins.casc.snakeyaml.emitter.Emitter;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.YAMLException;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.Event;
|
||||
import io.jenkins.plugins.casc.snakeyaml.introspector.BeanAccess;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Node;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Tag;
|
||||
import io.jenkins.plugins.casc.snakeyaml.parser.Parser;
|
||||
import io.jenkins.plugins.casc.snakeyaml.parser.ParserImpl;
|
||||
import io.jenkins.plugins.casc.snakeyaml.reader.StreamReader;
|
||||
import io.jenkins.plugins.casc.snakeyaml.reader.UnicodeReader;
|
||||
import io.jenkins.plugins.casc.snakeyaml.representer.Representer;
|
||||
import io.jenkins.plugins.casc.snakeyaml.resolver.Resolver;
|
||||
import io.jenkins.plugins.casc.snakeyaml.serializer.Serializer;
|
||||
|
||||
/**
|
||||
* Public YAML interface. Each Thread must have its own instance.
|
||||
*/
|
||||
public class Yaml {
|
||||
protected final Resolver resolver;
|
||||
private String name;
|
||||
protected BaseConstructor constructor;
|
||||
protected Representer representer;
|
||||
protected DumperOptions dumperOptions;
|
||||
protected LoaderOptions loadingConfig;
|
||||
|
||||
/**
|
||||
* Create Yaml instance. It is safe to create a few instances and use them
|
||||
* in different Threads.
|
||||
*/
|
||||
public Yaml() {
|
||||
this(new Constructor(), new Representer(), new DumperOptions(), new LoaderOptions(),
|
||||
new Resolver());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Yaml instance.
|
||||
*
|
||||
* @param dumperOptions
|
||||
* DumperOptions to configure outgoing objects
|
||||
*/
|
||||
public Yaml(DumperOptions dumperOptions) {
|
||||
this(new Constructor(), new Representer(), dumperOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Yaml instance.
|
||||
*
|
||||
* @param loadingConfig
|
||||
* LoadingConfig to control load behavior
|
||||
*/
|
||||
public Yaml(LoaderOptions loadingConfig) {
|
||||
this(new Constructor(), new Representer(), new DumperOptions(), loadingConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Yaml instance. It is safe to create a few instances and use them
|
||||
* in different Threads.
|
||||
*
|
||||
* @param representer
|
||||
* Representer to emit outgoing objects
|
||||
*/
|
||||
public Yaml(Representer representer) {
|
||||
this(new Constructor(), representer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Yaml instance. It is safe to create a few instances and use them
|
||||
* in different Threads.
|
||||
*
|
||||
* @param constructor
|
||||
* BaseConstructor to construct incoming documents
|
||||
*/
|
||||
public Yaml(BaseConstructor constructor) {
|
||||
this(constructor, new Representer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Yaml instance. It is safe to create a few instances and use them
|
||||
* in different Threads.
|
||||
*
|
||||
* @param constructor
|
||||
* BaseConstructor to construct incoming documents
|
||||
* @param representer
|
||||
* Representer to emit outgoing objects
|
||||
*/
|
||||
public Yaml(BaseConstructor constructor, Representer representer) {
|
||||
this(constructor, representer, initDumperOptions(representer));
|
||||
}
|
||||
|
||||
private static DumperOptions initDumperOptions(Representer representer) {
|
||||
DumperOptions dumperOptions = new DumperOptions();
|
||||
dumperOptions.setDefaultFlowStyle(representer.getDefaultFlowStyle());
|
||||
dumperOptions.setDefaultScalarStyle(representer.getDefaultScalarStyle());
|
||||
dumperOptions.setAllowReadOnlyProperties(representer.getPropertyUtils().isAllowReadOnlyProperties());
|
||||
dumperOptions.setTimeZone(representer.getTimeZone());
|
||||
return dumperOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Yaml instance. It is safe to create a few instances and use them
|
||||
* in different Threads.
|
||||
*
|
||||
* @param representer
|
||||
* Representer to emit outgoing objects
|
||||
* @param dumperOptions
|
||||
* DumperOptions to configure outgoing objects
|
||||
*/
|
||||
public Yaml(Representer representer, DumperOptions dumperOptions) {
|
||||
this(new Constructor(), representer, dumperOptions, new LoaderOptions(), new Resolver());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Yaml instance. It is safe to create a few instances and use them
|
||||
* in different Threads.
|
||||
*
|
||||
* @param constructor
|
||||
* BaseConstructor to construct incoming documents
|
||||
* @param representer
|
||||
* Representer to emit outgoing objects
|
||||
* @param dumperOptions
|
||||
* DumperOptions to configure outgoing objects
|
||||
*/
|
||||
public Yaml(BaseConstructor constructor, Representer representer, DumperOptions dumperOptions) {
|
||||
this(constructor, representer, dumperOptions, new LoaderOptions(), new Resolver());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Yaml instance. It is safe to create a few instances and use them
|
||||
* in different Threads.
|
||||
*
|
||||
* @param constructor
|
||||
* BaseConstructor to construct incoming documents
|
||||
* @param representer
|
||||
* Representer to emit outgoing objects
|
||||
* @param dumperOptions
|
||||
* DumperOptions to configure outgoing objects
|
||||
* @param loadingConfig
|
||||
* LoadingConfig to control load behavior
|
||||
*/
|
||||
public Yaml(BaseConstructor constructor, Representer representer, DumperOptions dumperOptions,
|
||||
LoaderOptions loadingConfig) {
|
||||
this(constructor, representer, dumperOptions, loadingConfig, new Resolver());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Yaml instance. It is safe to create a few instances and use them
|
||||
* in different Threads.
|
||||
*
|
||||
* @param constructor
|
||||
* BaseConstructor to construct incoming documents
|
||||
* @param representer
|
||||
* Representer to emit outgoing objects
|
||||
* @param dumperOptions
|
||||
* DumperOptions to configure outgoing objects
|
||||
* @param resolver
|
||||
* Resolver to detect implicit type
|
||||
*/
|
||||
public Yaml(BaseConstructor constructor, Representer representer, DumperOptions dumperOptions,
|
||||
Resolver resolver) {
|
||||
this(constructor, representer, dumperOptions, new LoaderOptions(), resolver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Yaml instance. It is safe to create a few instances and use them
|
||||
* in different Threads.
|
||||
*
|
||||
* @param constructor
|
||||
* BaseConstructor to construct incoming documents
|
||||
* @param representer
|
||||
* Representer to emit outgoing objects
|
||||
* @param dumperOptions
|
||||
* DumperOptions to configure outgoing objects
|
||||
* @param loadingConfig
|
||||
* LoadingConfig to control load behavior
|
||||
* @param resolver
|
||||
* Resolver to detect implicit type
|
||||
*/
|
||||
public Yaml(BaseConstructor constructor, Representer representer, DumperOptions dumperOptions,
|
||||
LoaderOptions loadingConfig, Resolver resolver) {
|
||||
if (!constructor.isExplicitPropertyUtils()) {
|
||||
constructor.setPropertyUtils(representer.getPropertyUtils());
|
||||
} else if (!representer.isExplicitPropertyUtils()) {
|
||||
representer.setPropertyUtils(constructor.getPropertyUtils());
|
||||
}
|
||||
this.constructor = constructor;
|
||||
this.constructor.setAllowDuplicateKeys(loadingConfig.isAllowDuplicateKeys());
|
||||
if (dumperOptions.getIndent() <= dumperOptions.getIndicatorIndent()) {
|
||||
throw new YAMLException("Indicator indent must be smaller then indent.");
|
||||
}
|
||||
representer.setDefaultFlowStyle(dumperOptions.getDefaultFlowStyle());
|
||||
representer.setDefaultScalarStyle(dumperOptions.getDefaultScalarStyle());
|
||||
representer.getPropertyUtils()
|
||||
.setAllowReadOnlyProperties(dumperOptions.isAllowReadOnlyProperties());
|
||||
representer.setTimeZone(dumperOptions.getTimeZone());
|
||||
this.representer = representer;
|
||||
this.dumperOptions = dumperOptions;
|
||||
this.loadingConfig = loadingConfig;
|
||||
this.resolver = resolver;
|
||||
this.name = "Yaml:" + System.identityHashCode(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize a Java object into a YAML String.
|
||||
*
|
||||
* @param data
|
||||
* Java object to be Serialized to YAML
|
||||
* @return YAML String
|
||||
*/
|
||||
public String dump(Object data) {
|
||||
List<Object> list = new ArrayList<Object>(1);
|
||||
list.add(data);
|
||||
return dumpAll(list.iterator());
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce the corresponding representation tree for a given Object.
|
||||
*
|
||||
* @see <a href="http://yaml.org/spec/1.1/#id859333">Figure 3.1. Processing
|
||||
* Overview</a>
|
||||
* @param data
|
||||
* instance to build the representation tree for
|
||||
* @return representation tree
|
||||
*/
|
||||
public Node represent(Object data) {
|
||||
return representer.represent(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize a sequence of Java objects into a YAML String.
|
||||
*
|
||||
* @param data
|
||||
* Iterator with Objects
|
||||
* @return YAML String with all the objects in proper sequence
|
||||
*/
|
||||
public String dumpAll(Iterator<? extends Object> data) {
|
||||
StringWriter buffer = new StringWriter();
|
||||
dumpAll(data, buffer, null);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize a Java object into a YAML stream.
|
||||
*
|
||||
* @param data
|
||||
* Java object to be serialized to YAML
|
||||
* @param output
|
||||
* stream to write to
|
||||
*/
|
||||
public void dump(Object data, Writer output) {
|
||||
List<Object> list = new ArrayList<Object>(1);
|
||||
list.add(data);
|
||||
dumpAll(list.iterator(), output, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize a sequence of Java objects into a YAML stream.
|
||||
*
|
||||
* @param data
|
||||
* Iterator with Objects
|
||||
* @param output
|
||||
* stream to write to
|
||||
*/
|
||||
public void dumpAll(Iterator<? extends Object> data, Writer output) {
|
||||
dumpAll(data, output, null);
|
||||
}
|
||||
|
||||
private void dumpAll(Iterator<? extends Object> data, Writer output, Tag rootTag) {
|
||||
Serializer serializer = new Serializer(new Emitter(output, dumperOptions), resolver,
|
||||
dumperOptions, rootTag);
|
||||
try {
|
||||
serializer.open();
|
||||
while (data.hasNext()) {
|
||||
Node node = representer.represent(data.next());
|
||||
serializer.serialize(node);
|
||||
}
|
||||
serializer.close();
|
||||
} catch (IOException e) {
|
||||
throw new YAMLException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Serialize a Java object into a YAML string. Override the default root tag
|
||||
* with <code>rootTag</code>.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* This method is similar to <code>Yaml.dump(data)</code> except that the
|
||||
* root tag for the whole document is replaced with the given tag. This has
|
||||
* two main uses.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* First, if the root tag is replaced with a standard YAML tag, such as
|
||||
* <code>Tag.MAP</code>, then the object will be dumped as a map. The root
|
||||
* tag will appear as <code>!!map</code>, or blank (implicit !!map).
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Second, if the root tag is replaced by a different custom tag, then the
|
||||
* document appears to be a different type when loaded. For example, if an
|
||||
* instance of MyClass is dumped with the tag !!YourClass, then it will be
|
||||
* handled as an instance of YourClass when loaded.
|
||||
* </p>
|
||||
*
|
||||
* @param data
|
||||
* Java object to be serialized to YAML
|
||||
* @param rootTag
|
||||
* the tag for the whole YAML document. The tag should be Tag.MAP
|
||||
* for a JavaBean to make the tag disappear (to use implicit tag
|
||||
* !!map). If <code>null</code> is provided then the standard tag
|
||||
* with the full class name is used.
|
||||
* @param flowStyle
|
||||
* flow style for the whole document. See Chapter 10. Collection
|
||||
* Styles http://yaml.org/spec/1.1/#id930798. If
|
||||
* <code>null</code> is provided then the flow style from
|
||||
* DumperOptions is used.
|
||||
*
|
||||
* @return YAML String
|
||||
*/
|
||||
public String dumpAs(Object data, Tag rootTag, FlowStyle flowStyle) {
|
||||
FlowStyle oldStyle = representer.getDefaultFlowStyle();
|
||||
if (flowStyle != null) {
|
||||
representer.setDefaultFlowStyle(flowStyle);
|
||||
}
|
||||
List<Object> list = new ArrayList<Object>(1);
|
||||
list.add(data);
|
||||
StringWriter buffer = new StringWriter();
|
||||
dumpAll(list.iterator(), buffer, rootTag);
|
||||
representer.setDefaultFlowStyle(oldStyle);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Serialize a Java object into a YAML string. Override the default root tag
|
||||
* with <code>Tag.MAP</code>.
|
||||
* </p>
|
||||
* <p>
|
||||
* This method is similar to <code>Yaml.dump(data)</code> except that the
|
||||
* root tag for the whole document is replaced with <code>Tag.MAP</code> tag
|
||||
* (implicit !!map).
|
||||
* </p>
|
||||
* <p>
|
||||
* Block Mapping is used as the collection style. See 10.2.2. Block Mappings
|
||||
* (http://yaml.org/spec/1.1/#id934537)
|
||||
* </p>
|
||||
*
|
||||
* @param data
|
||||
* Java object to be serialized to YAML
|
||||
* @return YAML String
|
||||
*/
|
||||
public String dumpAsMap(Object data) {
|
||||
return dumpAs(data, Tag.MAP, FlowStyle.BLOCK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize the representation tree into Events.
|
||||
*
|
||||
* @see <a href="http://yaml.org/spec/1.1/#id859333">Processing Overview</a>
|
||||
* @param data
|
||||
* representation tree
|
||||
* @return Event list
|
||||
*/
|
||||
public List<Event> serialize(Node data) {
|
||||
SilentEmitter emitter = new SilentEmitter();
|
||||
Serializer serializer = new Serializer(emitter, resolver, dumperOptions, null);
|
||||
try {
|
||||
serializer.open();
|
||||
serializer.serialize(data);
|
||||
serializer.close();
|
||||
} catch (IOException e) {
|
||||
throw new YAMLException(e);
|
||||
}
|
||||
return emitter.getEvents();
|
||||
}
|
||||
|
||||
private static class SilentEmitter implements Emitable {
|
||||
private List<Event> events = new ArrayList<Event>(100);
|
||||
|
||||
public List<Event> getEvents() {
|
||||
return events;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emit(Event event) throws IOException {
|
||||
events.add(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the only YAML document in a String and produce the corresponding
|
||||
* Java object. (Because the encoding in known BOM is not respected.)
|
||||
*
|
||||
* @param yaml
|
||||
* YAML data to load from (BOM must not be present)
|
||||
* @param <T>
|
||||
* the class of the instance to be created
|
||||
* @return parsed object
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T load(String yaml) {
|
||||
return (T) loadFromReader(new StreamReader(yaml), Object.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the only YAML document in a stream and produce the corresponding
|
||||
* Java object.
|
||||
*
|
||||
* @param io
|
||||
* data to load from (BOM is respected to detect encoding and removed from the data)
|
||||
* @param <T>
|
||||
* the class of the instance to be created
|
||||
* @return parsed object
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T load(InputStream io) {
|
||||
return (T) loadFromReader(new StreamReader(new UnicodeReader(io)), Object.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the only YAML document in a stream and produce the corresponding
|
||||
* Java object.
|
||||
*
|
||||
* @param io
|
||||
* data to load from (BOM must not be present)
|
||||
* @param <T>
|
||||
* the class of the instance to be created
|
||||
* @return parsed object
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T load(Reader io) {
|
||||
return (T) loadFromReader(new StreamReader(io), Object.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the only YAML document in a stream and produce the corresponding
|
||||
* Java object.
|
||||
*
|
||||
* @param <T>
|
||||
* Class is defined by the second argument
|
||||
* @param io
|
||||
* data to load from (BOM must not be present)
|
||||
* @param type
|
||||
* Class of the object to be created
|
||||
* @return parsed object
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T loadAs(Reader io, Class<T> type) {
|
||||
return (T) loadFromReader(new StreamReader(io), type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the only YAML document in a String and produce the corresponding
|
||||
* Java object. (Because the encoding in known BOM is not respected.)
|
||||
*
|
||||
* @param <T>
|
||||
* Class is defined by the second argument
|
||||
* @param yaml
|
||||
* YAML data to load from (BOM must not be present)
|
||||
* @param type
|
||||
* Class of the object to be created
|
||||
* @return parsed object
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T loadAs(String yaml, Class<T> type) {
|
||||
return (T) loadFromReader(new StreamReader(yaml), type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the only YAML document in a stream and produce the corresponding
|
||||
* Java object.
|
||||
*
|
||||
* @param <T>
|
||||
* Class is defined by the second argument
|
||||
* @param input
|
||||
* data to load from (BOM is respected to detect encoding and removed from the data)
|
||||
* @param type
|
||||
* Class of the object to be created
|
||||
* @return parsed object
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T loadAs(InputStream input, Class<T> type) {
|
||||
return (T) loadFromReader(new StreamReader(new UnicodeReader(input)), type);
|
||||
}
|
||||
|
||||
private Object loadFromReader(StreamReader sreader, Class<?> type) {
|
||||
Composer composer = new Composer(new ParserImpl(sreader), resolver);
|
||||
constructor.setComposer(composer);
|
||||
return constructor.getSingleData(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse all YAML documents in the Reader and produce corresponding Java
|
||||
* objects. The documents are parsed only when the iterator is invoked.
|
||||
*
|
||||
* @param yaml
|
||||
* YAML data to load from (BOM must not be present)
|
||||
* @return an Iterable over the parsed Java objects in this String in proper
|
||||
* sequence
|
||||
*/
|
||||
public Iterable<Object> loadAll(Reader yaml) {
|
||||
Composer composer = new Composer(new ParserImpl(new StreamReader(yaml)), resolver);
|
||||
constructor.setComposer(composer);
|
||||
Iterator<Object> result = new Iterator<Object>() {
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return constructor.checkData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object next() {
|
||||
return constructor.getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
return new YamlIterable(result);
|
||||
}
|
||||
|
||||
private static class YamlIterable implements Iterable<Object> {
|
||||
private Iterator<Object> iterator;
|
||||
|
||||
public YamlIterable(Iterator<Object> iterator) {
|
||||
this.iterator = iterator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Object> iterator() {
|
||||
return iterator;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse all YAML documents in a String and produce corresponding Java
|
||||
* objects. (Because the encoding in known BOM is not respected.) The
|
||||
* documents are parsed only when the iterator is invoked.
|
||||
*
|
||||
* @param yaml
|
||||
* YAML data to load from (BOM must not be present)
|
||||
* @return an Iterable over the parsed Java objects in this String in proper
|
||||
* sequence
|
||||
*/
|
||||
public Iterable<Object> loadAll(String yaml) {
|
||||
return loadAll(new StringReader(yaml));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse all YAML documents in a stream and produce corresponding Java
|
||||
* objects. The documents are parsed only when the iterator is invoked.
|
||||
*
|
||||
* @param yaml
|
||||
* YAML data to load from (BOM is respected to detect encoding and removed from the data)
|
||||
* @return an Iterable over the parsed Java objects in this stream in proper
|
||||
* sequence
|
||||
*/
|
||||
public Iterable<Object> loadAll(InputStream yaml) {
|
||||
return loadAll(new UnicodeReader(yaml));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the first YAML document in a stream and produce the corresponding
|
||||
* representation tree. (This is the opposite of the represent() method)
|
||||
*
|
||||
* @see <a href="http://yaml.org/spec/1.1/#id859333">Figure 3.1. Processing
|
||||
* Overview</a>
|
||||
* @param yaml
|
||||
* YAML document
|
||||
* @return parsed root Node for the specified YAML document
|
||||
*/
|
||||
public Node compose(Reader yaml) {
|
||||
Composer composer = new Composer(new ParserImpl(new StreamReader(yaml)), resolver);
|
||||
return composer.getSingleNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse all YAML documents in a stream and produce corresponding
|
||||
* representation trees.
|
||||
*
|
||||
* @see <a href="http://yaml.org/spec/1.1/#id859333">Processing Overview</a>
|
||||
* @param yaml
|
||||
* stream of YAML documents
|
||||
* @return parsed root Nodes for all the specified YAML documents
|
||||
*/
|
||||
public Iterable<Node> composeAll(Reader yaml) {
|
||||
final Composer composer = new Composer(new ParserImpl(new StreamReader(yaml)), resolver);
|
||||
Iterator<Node> result = new Iterator<Node>() {
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return composer.checkNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node next() {
|
||||
return composer.getNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
return new NodeIterable(result);
|
||||
}
|
||||
|
||||
private static class NodeIterable implements Iterable<Node> {
|
||||
private Iterator<Node> iterator;
|
||||
|
||||
public NodeIterable(Iterator<Node> iterator) {
|
||||
this.iterator = iterator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Node> iterator() {
|
||||
return iterator;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an implicit scalar detector. If an implicit scalar value matches the
|
||||
* given regexp, the corresponding tag is assigned to the scalar.
|
||||
*
|
||||
* @param tag
|
||||
* tag to assign to the node
|
||||
* @param regexp
|
||||
* regular expression to match against
|
||||
* @param first
|
||||
* a sequence of possible initial characters or null (which means
|
||||
* any).
|
||||
*/
|
||||
public void addImplicitResolver(Tag tag, Pattern regexp, String first) {
|
||||
resolver.addImplicitResolver(tag, regexp, first);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a meaningful name. It simplifies debugging in a multi-threaded
|
||||
* environment. If nothing is set explicitly the address of the instance is
|
||||
* returned.
|
||||
*
|
||||
* @return human readable name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a meaningful name to be shown in toString()
|
||||
*
|
||||
* @param name
|
||||
* human readable name
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a YAML stream and produce parsing events.
|
||||
*
|
||||
* @see <a href="http://yaml.org/spec/1.1/#id859333">Processing Overview</a>
|
||||
* @param yaml
|
||||
* YAML document(s)
|
||||
* @return parsed events
|
||||
*/
|
||||
public Iterable<Event> parse(Reader yaml) {
|
||||
final Parser parser = new ParserImpl(new StreamReader(yaml));
|
||||
Iterator<Event> result = new Iterator<Event>() {
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return parser.peekEvent() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Event next() {
|
||||
return parser.getEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
return new EventIterable(result);
|
||||
}
|
||||
|
||||
private static class EventIterable implements Iterable<Event> {
|
||||
private Iterator<Event> iterator;
|
||||
|
||||
public EventIterable(Iterator<Event> iterator) {
|
||||
this.iterator = iterator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Event> iterator() {
|
||||
return iterator;
|
||||
}
|
||||
}
|
||||
|
||||
public void setBeanAccess(BeanAccess beanAccess) {
|
||||
constructor.getPropertyUtils().setBeanAccess(beanAccess);
|
||||
representer.getPropertyUtils().setBeanAccess(beanAccess);
|
||||
}
|
||||
|
||||
public void addTypeDescription(TypeDescription td) {
|
||||
constructor.addTypeDescription(td);
|
||||
representer.addTypeDescription(td);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,238 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.composer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.AliasEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.Event;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.MappingStartEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.NodeEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.ScalarEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.SequenceStartEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.MappingNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Node;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.NodeId;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.NodeTuple;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.ScalarNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.SequenceNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Tag;
|
||||
import io.jenkins.plugins.casc.snakeyaml.parser.Parser;
|
||||
import io.jenkins.plugins.casc.snakeyaml.resolver.Resolver;
|
||||
|
||||
/**
|
||||
* Creates a node graph from parser events.
|
||||
* <p>
|
||||
* Corresponds to the 'Compose' step as described in chapter 3.1 of the
|
||||
* <a href="http://yaml.org/spec/1.1/">YAML Specification</a>.
|
||||
* </p>
|
||||
*/
|
||||
public class Composer {
|
||||
protected final Parser parser;
|
||||
private final Resolver resolver;
|
||||
private final Map<String, Node> anchors;
|
||||
private final Set<Node> recursiveNodes;
|
||||
|
||||
public Composer(Parser parser, Resolver resolver) {
|
||||
this.parser = parser;
|
||||
this.resolver = resolver;
|
||||
this.anchors = new HashMap<String, Node>();
|
||||
this.recursiveNodes = new HashSet<Node>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if further documents are available.
|
||||
*
|
||||
* @return <code>true</code> if there is at least one more document.
|
||||
*/
|
||||
public boolean checkNode() {
|
||||
// Drop the STREAM-START event.
|
||||
if (parser.checkEvent(Event.ID.StreamStart)) {
|
||||
parser.getEvent();
|
||||
}
|
||||
// If there are more documents available?
|
||||
return !parser.checkEvent(Event.ID.StreamEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads and composes the next document.
|
||||
*
|
||||
* @return The root node of the document or <code>null</code> if no more
|
||||
* documents are available.
|
||||
*/
|
||||
public Node getNode() {
|
||||
// Drop the DOCUMENT-START event.
|
||||
parser.getEvent();
|
||||
// Compose the root node.
|
||||
Node node = composeNode(null);
|
||||
// Drop the DOCUMENT-END event.
|
||||
parser.getEvent();
|
||||
this.anchors.clear();
|
||||
recursiveNodes.clear();
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a document from a source that contains only one document.
|
||||
* <p>
|
||||
* If the stream contains more than one document an exception is thrown.
|
||||
* </p>
|
||||
*
|
||||
* @return The root node of the document or <code>null</code> if no document
|
||||
* is available.
|
||||
*/
|
||||
public Node getSingleNode() {
|
||||
// Drop the STREAM-START event.
|
||||
parser.getEvent();
|
||||
// Compose a document if the stream is not empty.
|
||||
Node document = null;
|
||||
if (!parser.checkEvent(Event.ID.StreamEnd)) {
|
||||
document = getNode();
|
||||
}
|
||||
// Ensure that the stream contains no more documents.
|
||||
if (!parser.checkEvent(Event.ID.StreamEnd)) {
|
||||
Event event = parser.getEvent();
|
||||
throw new ComposerException("expected a single document in the stream",
|
||||
document.getStartMark(), "but found another document", event.getStartMark());
|
||||
}
|
||||
// Drop the STREAM-END event.
|
||||
parser.getEvent();
|
||||
return document;
|
||||
}
|
||||
|
||||
private Node composeNode(Node parent) {
|
||||
if (parent != null) recursiveNodes.add(parent);
|
||||
final Node node;
|
||||
if (parser.checkEvent(Event.ID.Alias)) {
|
||||
AliasEvent event = (AliasEvent) parser.getEvent();
|
||||
String anchor = event.getAnchor();
|
||||
if (!anchors.containsKey(anchor)) {
|
||||
throw new ComposerException(null, null, "found undefined alias " + anchor,
|
||||
event.getStartMark());
|
||||
}
|
||||
node = anchors.get(anchor);
|
||||
if (recursiveNodes.remove(node)) {
|
||||
node.setTwoStepsConstruction(true);
|
||||
}
|
||||
} else {
|
||||
NodeEvent event = (NodeEvent) parser.peekEvent();
|
||||
String anchor = event.getAnchor();
|
||||
// the check for duplicate anchors has been removed (issue 174)
|
||||
if (parser.checkEvent(Event.ID.Scalar)) {
|
||||
node = composeScalarNode(anchor);
|
||||
} else if (parser.checkEvent(Event.ID.SequenceStart)) {
|
||||
node = composeSequenceNode(anchor);
|
||||
} else {
|
||||
node = composeMappingNode(anchor);
|
||||
}
|
||||
}
|
||||
recursiveNodes.remove(parent);
|
||||
return node;
|
||||
}
|
||||
|
||||
protected Node composeScalarNode(String anchor) {
|
||||
ScalarEvent ev = (ScalarEvent) parser.getEvent();
|
||||
String tag = ev.getTag();
|
||||
boolean resolved = false;
|
||||
Tag nodeTag;
|
||||
if (tag == null || tag.equals("!")) {
|
||||
nodeTag = resolver.resolve(NodeId.scalar, ev.getValue(),
|
||||
ev.getImplicit().canOmitTagInPlainScalar());
|
||||
resolved = true;
|
||||
} else {
|
||||
nodeTag = new Tag(tag);
|
||||
}
|
||||
Node node = new ScalarNode(nodeTag, resolved, ev.getValue(), ev.getStartMark(),
|
||||
ev.getEndMark(), ev.getScalarStyle());
|
||||
if (anchor != null) {
|
||||
anchors.put(anchor, node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
protected Node composeSequenceNode(String anchor) {
|
||||
SequenceStartEvent startEvent = (SequenceStartEvent) parser.getEvent();
|
||||
String tag = startEvent.getTag();
|
||||
Tag nodeTag;
|
||||
boolean resolved = false;
|
||||
if (tag == null || tag.equals("!")) {
|
||||
nodeTag = resolver.resolve(NodeId.sequence, null, startEvent.getImplicit());
|
||||
resolved = true;
|
||||
} else {
|
||||
nodeTag = new Tag(tag);
|
||||
}
|
||||
final ArrayList<Node> children = new ArrayList<Node>();
|
||||
SequenceNode node = new SequenceNode(nodeTag, resolved, children, startEvent.getStartMark(),
|
||||
null, startEvent.getFlowStyle());
|
||||
if (anchor != null) {
|
||||
anchors.put(anchor, node);
|
||||
}
|
||||
while (!parser.checkEvent(Event.ID.SequenceEnd)) {
|
||||
children.add(composeNode(node));
|
||||
}
|
||||
Event endEvent = parser.getEvent();
|
||||
node.setEndMark(endEvent.getEndMark());
|
||||
return node;
|
||||
}
|
||||
|
||||
protected Node composeMappingNode(String anchor) {
|
||||
MappingStartEvent startEvent = (MappingStartEvent) parser.getEvent();
|
||||
String tag = startEvent.getTag();
|
||||
Tag nodeTag;
|
||||
boolean resolved = false;
|
||||
if (tag == null || tag.equals("!")) {
|
||||
nodeTag = resolver.resolve(NodeId.mapping, null, startEvent.getImplicit());
|
||||
resolved = true;
|
||||
} else {
|
||||
nodeTag = new Tag(tag);
|
||||
}
|
||||
|
||||
final List<NodeTuple> children = new ArrayList<NodeTuple>();
|
||||
MappingNode node = new MappingNode(nodeTag, resolved, children, startEvent.getStartMark(),
|
||||
null, startEvent.getFlowStyle());
|
||||
if (anchor != null) {
|
||||
anchors.put(anchor, node);
|
||||
}
|
||||
while (!parser.checkEvent(Event.ID.MappingEnd)) {
|
||||
composeMappingChildren(children, node);
|
||||
}
|
||||
Event endEvent = parser.getEvent();
|
||||
node.setEndMark(endEvent.getEndMark());
|
||||
return node;
|
||||
}
|
||||
|
||||
protected void composeMappingChildren(List<NodeTuple> children, MappingNode node) {
|
||||
Node itemKey = composeKeyNode(node);
|
||||
if (itemKey.getTag().equals(Tag.MERGE)) {
|
||||
node.setMerged(true);
|
||||
}
|
||||
Node itemValue = composeValueNode(node);
|
||||
children.add(new NodeTuple(itemKey, itemValue));
|
||||
}
|
||||
|
||||
protected Node composeKeyNode(MappingNode node) {
|
||||
return composeNode(node);
|
||||
}
|
||||
|
||||
protected Node composeValueNode(MappingNode node) {
|
||||
return composeNode(node);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.composer;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.MarkedYAMLException;
|
||||
|
||||
public class ComposerException extends MarkedYAMLException {
|
||||
private static final long serialVersionUID = 2146314636913113935L;
|
||||
|
||||
protected ComposerException(String context, Mark contextMark, String problem, Mark problemMark) {
|
||||
super(context, contextMark, problem, problemMark);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.constructor;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.YAMLException;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Node;
|
||||
|
||||
/**
|
||||
* Because recursive structures are not very common we provide a way to save
|
||||
* some typing when extending a constructor
|
||||
*/
|
||||
public abstract class AbstractConstruct implements Construct {
|
||||
|
||||
/**
|
||||
* Fail with a reminder to provide the seconds step for a recursive
|
||||
* structure
|
||||
*
|
||||
* @see io.jenkins.plugins.casc.snakeyaml.constructor.Construct#construct2ndStep(io.jenkins.plugins.casc.snakeyaml.nodes.Node,
|
||||
* java.lang.Object)
|
||||
*/
|
||||
public void construct2ndStep(Node node, Object data) {
|
||||
if (node.isTwoStepsConstruction()) {
|
||||
throw new IllegalStateException("Not Implemented in " + getClass().getName());
|
||||
} else {
|
||||
throw new YAMLException("Unexpected recursive structure for Node: " + node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,575 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.constructor;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.TypeDescription;
|
||||
import io.jenkins.plugins.casc.snakeyaml.composer.Composer;
|
||||
import io.jenkins.plugins.casc.snakeyaml.composer.ComposerException;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.YAMLException;
|
||||
import io.jenkins.plugins.casc.snakeyaml.introspector.PropertyUtils;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.CollectionNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.MappingNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Node;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.NodeId;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.NodeTuple;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.ScalarNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.SequenceNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Tag;
|
||||
|
||||
public abstract class BaseConstructor {
|
||||
/**
|
||||
* It maps the node kind to the the Construct implementation. When the
|
||||
* runtime class is known then the implicit tag is ignored.
|
||||
*/
|
||||
protected final Map<NodeId, Construct> yamlClassConstructors = new EnumMap<NodeId, Construct>(
|
||||
NodeId.class);
|
||||
/**
|
||||
* It maps the (explicit or implicit) tag to the Construct implementation.
|
||||
* It is used:
|
||||
* 1) explicit tag - if present.
|
||||
* 2) implicit tag - when the runtime class of the instance is unknown (the
|
||||
* node has the Object.class)
|
||||
*/
|
||||
protected final Map<Tag, Construct> yamlConstructors = new HashMap<Tag, Construct>();
|
||||
/**
|
||||
* It maps the (explicit or implicit) tag to the Construct implementation.
|
||||
* It is used when no exact match found.
|
||||
*/
|
||||
protected final Map<String, Construct> yamlMultiConstructors = new HashMap<String, Construct>();
|
||||
|
||||
protected Composer composer;
|
||||
final Map<Node, Object> constructedObjects;
|
||||
private final Set<Node> recursiveObjects;
|
||||
private final ArrayList<RecursiveTuple<Map<Object, Object>, RecursiveTuple<Object, Object>>> maps2fill;
|
||||
private final ArrayList<RecursiveTuple<Set<Object>, Object>> sets2fill;
|
||||
|
||||
protected Tag rootTag;
|
||||
private PropertyUtils propertyUtils;
|
||||
private boolean explicitPropertyUtils;
|
||||
private boolean allowDuplicateKeys = true;
|
||||
|
||||
protected final Map<Class<? extends Object>, TypeDescription> typeDefinitions;
|
||||
protected final Map<Tag, Class<? extends Object>> typeTags;
|
||||
|
||||
public BaseConstructor() {
|
||||
constructedObjects = new HashMap<Node, Object>();
|
||||
recursiveObjects = new HashSet<Node>();
|
||||
maps2fill = new ArrayList<RecursiveTuple<Map<Object, Object>, RecursiveTuple<Object, Object>>>();
|
||||
sets2fill = new ArrayList<RecursiveTuple<Set<Object>, Object>>();
|
||||
typeDefinitions = new HashMap<Class<? extends Object>, TypeDescription>();
|
||||
typeTags = new HashMap<Tag, Class<? extends Object>>();
|
||||
|
||||
rootTag = null;
|
||||
explicitPropertyUtils = false;
|
||||
|
||||
typeDefinitions.put(SortedMap.class, new TypeDescription(SortedMap.class, Tag.OMAP,
|
||||
TreeMap.class));
|
||||
typeDefinitions.put(SortedSet.class, new TypeDescription(SortedSet.class, Tag.SET,
|
||||
TreeSet.class));
|
||||
}
|
||||
|
||||
public void setComposer(Composer composer) {
|
||||
this.composer = composer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if more documents available
|
||||
*
|
||||
* @return true when there are more YAML documents in the stream
|
||||
*/
|
||||
public boolean checkData() {
|
||||
// If there are more documents available?
|
||||
return composer.checkNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct and return the next document
|
||||
*
|
||||
* @return constructed instance
|
||||
*/
|
||||
public Object getData() {
|
||||
// Construct and return the next document.
|
||||
composer.checkNode();
|
||||
Node node = composer.getNode();
|
||||
if (rootTag != null) {
|
||||
node.setTag(rootTag);
|
||||
}
|
||||
return constructDocument(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the stream contains a single document and construct it
|
||||
*
|
||||
* @param type the class of the instance being created
|
||||
* @return constructed instance
|
||||
* @throws ComposerException in case there are more documents in the stream
|
||||
*/
|
||||
public Object getSingleData(Class<?> type) {
|
||||
// Ensure that the stream contains a single document and construct it
|
||||
Node node = composer.getSingleNode();
|
||||
if (node != null && !Tag.NULL.equals(node.getTag())) {
|
||||
if (Object.class != type) {
|
||||
node.setTag(new Tag(type));
|
||||
} else if (rootTag != null) {
|
||||
node.setTag(rootTag);
|
||||
}
|
||||
return constructDocument(node);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct complete YAML document. Call the second step in case of
|
||||
* recursive structures. At the end cleans all the state.
|
||||
*
|
||||
* @param node root Node
|
||||
* @return Java instance
|
||||
*/
|
||||
protected final Object constructDocument(Node node) {
|
||||
Object data = constructObject(node);
|
||||
fillRecursive();
|
||||
constructedObjects.clear();
|
||||
recursiveObjects.clear();
|
||||
return data;
|
||||
}
|
||||
|
||||
private void fillRecursive() {
|
||||
if (!maps2fill.isEmpty()) {
|
||||
for (RecursiveTuple<Map<Object, Object>, RecursiveTuple<Object, Object>> entry : maps2fill) {
|
||||
RecursiveTuple<Object, Object> key_value = entry._2();
|
||||
entry._1().put(key_value._1(), key_value._2());
|
||||
}
|
||||
maps2fill.clear();
|
||||
}
|
||||
if (!sets2fill.isEmpty()) {
|
||||
for (RecursiveTuple<Set<Object>, Object> value : sets2fill) {
|
||||
value._1().add(value._2());
|
||||
}
|
||||
sets2fill.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct object from the specified Node. Return existing instance if the
|
||||
* node is already constructed.
|
||||
*
|
||||
* @param node Node to be constructed
|
||||
* @return Java instance
|
||||
*/
|
||||
protected Object constructObject(Node node) {
|
||||
if (constructedObjects.containsKey(node)) {
|
||||
return constructedObjects.get(node);
|
||||
}
|
||||
return constructObjectNoCheck(node);
|
||||
}
|
||||
|
||||
protected Object constructObjectNoCheck(Node node) {
|
||||
if (recursiveObjects.contains(node)) {
|
||||
throw new ConstructorException(null, null, "found unconstructable recursive node",
|
||||
node.getStartMark());
|
||||
}
|
||||
recursiveObjects.add(node);
|
||||
Construct constructor = getConstructor(node);
|
||||
Object data = (constructedObjects.containsKey(node)) ? constructedObjects.get(node)
|
||||
: constructor.construct(node);
|
||||
|
||||
finalizeConstruction(node, data);
|
||||
constructedObjects.put(node, data);
|
||||
recursiveObjects.remove(node);
|
||||
if (node.isTwoStepsConstruction()) {
|
||||
constructor.construct2ndStep(node, data);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the constructor to construct the Node. For implicit tags if the
|
||||
* runtime class is known a dedicated Construct implementation is used.
|
||||
* Otherwise the constructor is chosen by the tag.
|
||||
*
|
||||
* @param node {@link Node} to construct an instance from
|
||||
* @return {@link Construct} implementation for the specified node
|
||||
*/
|
||||
protected Construct getConstructor(Node node) {
|
||||
if (node.useClassConstructor()) {
|
||||
return yamlClassConstructors.get(node.getNodeId());
|
||||
} else {
|
||||
Construct constructor = yamlConstructors.get(node.getTag());
|
||||
if (constructor == null) {
|
||||
for (String prefix : yamlMultiConstructors.keySet()) {
|
||||
if (node.getTag().startsWith(prefix)) {
|
||||
return yamlMultiConstructors.get(prefix);
|
||||
}
|
||||
}
|
||||
return yamlConstructors.get(null);
|
||||
}
|
||||
return constructor;
|
||||
}
|
||||
}
|
||||
|
||||
protected String constructScalar(ScalarNode node) {
|
||||
return node.getValue();
|
||||
}
|
||||
|
||||
// >>>> DEFAULTS >>>>
|
||||
protected List<Object> createDefaultList(int initSize) {
|
||||
return new ArrayList<Object>(initSize);
|
||||
}
|
||||
|
||||
protected Set<Object> createDefaultSet(int initSize) {
|
||||
return new LinkedHashSet<Object>(initSize);
|
||||
}
|
||||
|
||||
protected Map<Object, Object> createDefaultMap(int initSize) {
|
||||
// respect order from YAML document
|
||||
return new LinkedHashMap<Object, Object>(initSize);
|
||||
}
|
||||
|
||||
protected Object createArray(Class<?> type, int size) {
|
||||
return Array.newInstance(type.getComponentType(), size);
|
||||
}
|
||||
|
||||
// <<<< DEFAULTS <<<<
|
||||
|
||||
protected Object finalizeConstruction(Node node, Object data) {
|
||||
final Class<? extends Object> type = node.getType();
|
||||
if (typeDefinitions.containsKey(type)) {
|
||||
return typeDefinitions.get(type).finalizeConstruction(data);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
// >>>> NEW instance
|
||||
protected Object newInstance(Node node) {
|
||||
try {
|
||||
return newInstance(Object.class, node);
|
||||
} catch (InstantiationException e) {
|
||||
throw new YAMLException(e);
|
||||
}
|
||||
}
|
||||
|
||||
final protected Object newInstance(Class<?> ancestor, Node node) throws InstantiationException {
|
||||
return newInstance(ancestor, node, true);
|
||||
}
|
||||
|
||||
protected Object newInstance(Class<?> ancestor, Node node, boolean tryDefault)
|
||||
throws InstantiationException {
|
||||
final Class<? extends Object> type = node.getType();
|
||||
if (typeDefinitions.containsKey(type)) {
|
||||
TypeDescription td = typeDefinitions.get(type);
|
||||
final Object instance = td.newInstance(node);
|
||||
if (instance != null) {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
if (tryDefault) {
|
||||
/*
|
||||
* Removed <code> have InstantiationException in case of abstract
|
||||
* type
|
||||
*/
|
||||
if (ancestor.isAssignableFrom(type) && !Modifier.isAbstract(type.getModifiers())) {
|
||||
try {
|
||||
java.lang.reflect.Constructor<?> c = type.getDeclaredConstructor();
|
||||
c.setAccessible(true);
|
||||
return c.newInstance();
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new InstantiationException("NoSuchMethodException:"
|
||||
+ e.getLocalizedMessage());
|
||||
} catch (Exception e) {
|
||||
throw new YAMLException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new InstantiationException();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Set<Object> newSet(CollectionNode<?> node) {
|
||||
try {
|
||||
return (Set<Object>) newInstance(Set.class, node);
|
||||
} catch (InstantiationException e) {
|
||||
return createDefaultSet(node.getValue().size());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<Object> newList(SequenceNode node) {
|
||||
try {
|
||||
return (List<Object>) newInstance(List.class, node);
|
||||
} catch (InstantiationException e) {
|
||||
return createDefaultList(node.getValue().size());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Map<Object, Object> newMap(MappingNode node) {
|
||||
try {
|
||||
return (Map<Object, Object>) newInstance(Map.class, node);
|
||||
} catch (InstantiationException e) {
|
||||
return createDefaultMap(node.getValue().size());
|
||||
}
|
||||
}
|
||||
|
||||
// <<<< NEW instance
|
||||
|
||||
// >>>> Construct => NEW, 2ndStep(filling)
|
||||
protected List<? extends Object> constructSequence(SequenceNode node) {
|
||||
List<Object> result = newList(node);
|
||||
constructSequenceStep2(node, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Set<? extends Object> constructSet(SequenceNode node) {
|
||||
Set<Object> result = newSet(node);
|
||||
constructSequenceStep2(node, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Object constructArray(SequenceNode node) {
|
||||
return constructArrayStep2(node, createArray(node.getType(), node.getValue().size()));
|
||||
}
|
||||
|
||||
protected void constructSequenceStep2(SequenceNode node, Collection<Object> collection) {
|
||||
for (Node child : node.getValue()) {
|
||||
collection.add(constructObject(child));
|
||||
}
|
||||
}
|
||||
|
||||
protected Object constructArrayStep2(SequenceNode node, Object array) {
|
||||
final Class<?> componentType = node.getType().getComponentType();
|
||||
|
||||
int index = 0;
|
||||
for (Node child : node.getValue()) {
|
||||
// Handle multi-dimensional arrays...
|
||||
if (child.getType() == Object.class) {
|
||||
child.setType(componentType);
|
||||
}
|
||||
|
||||
final Object value = constructObject(child);
|
||||
|
||||
if (componentType.isPrimitive()) {
|
||||
// Null values are disallowed for primitives
|
||||
if (value == null) {
|
||||
throw new NullPointerException(
|
||||
"Unable to construct element value for " + child);
|
||||
}
|
||||
|
||||
// Primitive arrays require quite a lot of work.
|
||||
if (byte.class.equals(componentType)) {
|
||||
Array.setByte(array, index, ((Number) value).byteValue());
|
||||
|
||||
} else if (short.class.equals(componentType)) {
|
||||
Array.setShort(array, index, ((Number) value).shortValue());
|
||||
|
||||
} else if (int.class.equals(componentType)) {
|
||||
Array.setInt(array, index, ((Number) value).intValue());
|
||||
|
||||
} else if (long.class.equals(componentType)) {
|
||||
Array.setLong(array, index, ((Number) value).longValue());
|
||||
|
||||
} else if (float.class.equals(componentType)) {
|
||||
Array.setFloat(array, index, ((Number) value).floatValue());
|
||||
|
||||
} else if (double.class.equals(componentType)) {
|
||||
Array.setDouble(array, index, ((Number) value).doubleValue());
|
||||
|
||||
} else if (char.class.equals(componentType)) {
|
||||
Array.setChar(array, index, ((Character) value).charValue());
|
||||
|
||||
} else if (boolean.class.equals(componentType)) {
|
||||
Array.setBoolean(array, index, ((Boolean) value).booleanValue());
|
||||
|
||||
} else {
|
||||
throw new YAMLException("unexpected primitive type");
|
||||
}
|
||||
|
||||
} else {
|
||||
// Non-primitive arrays can simply be assigned:
|
||||
Array.set(array, index, value);
|
||||
}
|
||||
|
||||
++index;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
protected Set<Object> constructSet(MappingNode node) {
|
||||
final Set<Object> set = newSet(node);
|
||||
constructSet2ndStep(node, set);
|
||||
return set;
|
||||
}
|
||||
|
||||
protected Map<Object, Object> constructMapping(MappingNode node) {
|
||||
final Map<Object, Object> mapping = newMap(node);
|
||||
constructMapping2ndStep(node, mapping);
|
||||
return mapping;
|
||||
}
|
||||
|
||||
protected void constructMapping2ndStep(MappingNode node, Map<Object, Object> mapping) {
|
||||
List<NodeTuple> nodeValue = node.getValue();
|
||||
for (NodeTuple tuple : nodeValue) {
|
||||
Node keyNode = tuple.getKeyNode();
|
||||
Node valueNode = tuple.getValueNode();
|
||||
Object key = constructObject(keyNode);
|
||||
if (key != null) {
|
||||
try {
|
||||
key.hashCode();// check circular dependencies
|
||||
} catch (Exception e) {
|
||||
throw new ConstructorException("while constructing a mapping",
|
||||
node.getStartMark(), "found unacceptable key " + key,
|
||||
tuple.getKeyNode().getStartMark(), e);
|
||||
}
|
||||
}
|
||||
Object value = constructObject(valueNode);
|
||||
if (keyNode.isTwoStepsConstruction()) {
|
||||
/*
|
||||
* if keyObject is created it 2 steps we should postpone putting
|
||||
* it in map because it may have different hash after
|
||||
* initialization compared to clean just created one. And map of
|
||||
* course does not observe key hashCode changes.
|
||||
*/
|
||||
maps2fill.add(0,
|
||||
new RecursiveTuple<Map<Object, Object>, RecursiveTuple<Object, Object>>(
|
||||
mapping, new RecursiveTuple<Object, Object>(key, value)));
|
||||
} else {
|
||||
mapping.put(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void constructSet2ndStep(MappingNode node, Set<Object> set) {
|
||||
List<NodeTuple> nodeValue = node.getValue();
|
||||
for (NodeTuple tuple : nodeValue) {
|
||||
Node keyNode = tuple.getKeyNode();
|
||||
Object key = constructObject(keyNode);
|
||||
if (key != null) {
|
||||
try {
|
||||
key.hashCode();// check circular dependencies
|
||||
} catch (Exception e) {
|
||||
throw new ConstructorException("while constructing a Set", node.getStartMark(),
|
||||
"found unacceptable key " + key, tuple.getKeyNode().getStartMark(), e);
|
||||
}
|
||||
}
|
||||
if (keyNode.isTwoStepsConstruction()) {
|
||||
/*
|
||||
* if keyObject is created it 2 steps we should postpone putting
|
||||
* it into the set because it may have different hash after
|
||||
* initialization compared to clean just created one. And set of
|
||||
* course does not observe value hashCode changes.
|
||||
*/
|
||||
sets2fill.add(0, new RecursiveTuple<Set<Object>, Object>(set, key));
|
||||
} else {
|
||||
set.add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// <<<< Costruct => NEW, 2ndStep(filling)
|
||||
|
||||
// TODO protected List<Object[]> constructPairs(MappingNode node) {
|
||||
// List<Object[]> pairs = new LinkedList<Object[]>();
|
||||
// List<Node[]> nodeValue = (List<Node[]>) node.getValue();
|
||||
// for (Iterator<Node[]> iter = nodeValue.iterator(); iter.hasNext();) {
|
||||
// Node[] tuple = iter.next();
|
||||
// Object key = constructObject(Object.class, tuple[0]);
|
||||
// Object value = constructObject(Object.class, tuple[1]);
|
||||
// pairs.add(new Object[] { key, value });
|
||||
// }
|
||||
// return pairs;
|
||||
// }
|
||||
|
||||
public void setPropertyUtils(PropertyUtils propertyUtils) {
|
||||
this.propertyUtils = propertyUtils;
|
||||
explicitPropertyUtils = true;
|
||||
Collection<TypeDescription> tds = typeDefinitions.values();
|
||||
for (TypeDescription typeDescription : tds) {
|
||||
typeDescription.setPropertyUtils(propertyUtils);
|
||||
}
|
||||
}
|
||||
|
||||
public final PropertyUtils getPropertyUtils() {
|
||||
if (propertyUtils == null) {
|
||||
propertyUtils = new PropertyUtils();
|
||||
}
|
||||
return propertyUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make YAML aware how to parse a custom Class. If there is no root Class
|
||||
* assigned in constructor then the 'root' property of this definition is
|
||||
* respected.
|
||||
*
|
||||
* @param definition to be added to the Constructor
|
||||
* @return the previous value associated with <tt>definition</tt>, or
|
||||
* <tt>null</tt> if there was no mapping for <tt>definition</tt>.
|
||||
*/
|
||||
public TypeDescription addTypeDescription(TypeDescription definition) {
|
||||
if (definition == null) {
|
||||
throw new NullPointerException("TypeDescription is required.");
|
||||
}
|
||||
Tag tag = definition.getTag();
|
||||
typeTags.put(tag, definition.getType());
|
||||
definition.setPropertyUtils(getPropertyUtils());
|
||||
return typeDefinitions.put(definition.getType(), definition);
|
||||
}
|
||||
|
||||
private static class RecursiveTuple<T, K> {
|
||||
private final T _1;
|
||||
private final K _2;
|
||||
|
||||
public RecursiveTuple(T _1, K _2) {
|
||||
this._1 = _1;
|
||||
this._2 = _2;
|
||||
}
|
||||
|
||||
public K _2() {
|
||||
return _2;
|
||||
}
|
||||
|
||||
public T _1() {
|
||||
return _1;
|
||||
}
|
||||
}
|
||||
|
||||
public final boolean isExplicitPropertyUtils() {
|
||||
return explicitPropertyUtils;
|
||||
}
|
||||
|
||||
public boolean isAllowDuplicateKeys() {
|
||||
return allowDuplicateKeys;
|
||||
}
|
||||
|
||||
public void setAllowDuplicateKeys(boolean allowDuplicateKeys) {
|
||||
this.allowDuplicateKeys = allowDuplicateKeys;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.constructor;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Node;
|
||||
|
||||
/**
|
||||
* Provide a way to construct a Java instance out of the composed Node. Support
|
||||
* recursive objects if it is required. (create Native Data Structure out of
|
||||
* Node Graph)
|
||||
*
|
||||
* @see <a href="http://yaml.org/spec/1.1/#id859109">Chapter 3. Processing YAML
|
||||
* Information</a>
|
||||
*/
|
||||
public interface Construct {
|
||||
/**
|
||||
* Construct a Java instance with all the properties injected when it is
|
||||
* possible.
|
||||
*
|
||||
* @param node
|
||||
* composed Node
|
||||
* @return a complete Java instance
|
||||
*/
|
||||
Object construct(Node node);
|
||||
|
||||
/**
|
||||
* Apply the second step when constructing recursive structures. Because the
|
||||
* instance is already created it can assign a reference to itself.
|
||||
*
|
||||
* @param node
|
||||
* composed Node
|
||||
* @param object
|
||||
* the instance constructed earlier by
|
||||
* <code>construct(Node node)</code> for the provided Node
|
||||
*/
|
||||
void construct2ndStep(Node node, Object object);
|
||||
}
|
||||
|
|
@ -0,0 +1,658 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.constructor;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.TypeDescription;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.YAMLException;
|
||||
import io.jenkins.plugins.casc.snakeyaml.introspector.Property;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.MappingNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Node;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.NodeId;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.NodeTuple;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.ScalarNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.SequenceNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Tag;
|
||||
|
||||
/**
|
||||
* Construct a custom Java instance.
|
||||
*/
|
||||
public class Constructor extends SafeConstructor {
|
||||
|
||||
public Constructor() {
|
||||
this(Object.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Constructor for the specified class as the root.
|
||||
*
|
||||
* @param theRoot
|
||||
* - the class (usually JavaBean) to be constructed
|
||||
*/
|
||||
public Constructor(Class<? extends Object> theRoot) {
|
||||
this(new TypeDescription(checkRoot(theRoot)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ugly Java way to check the argument in the constructor
|
||||
*/
|
||||
private static Class<? extends Object> checkRoot(Class<? extends Object> theRoot) {
|
||||
if (theRoot == null) {
|
||||
throw new NullPointerException("Root class must be provided.");
|
||||
} else
|
||||
return theRoot;
|
||||
}
|
||||
|
||||
public Constructor(TypeDescription theRoot) {
|
||||
this(theRoot, null);
|
||||
}
|
||||
|
||||
public Constructor(TypeDescription theRoot, Collection<TypeDescription> moreTDs) {
|
||||
if (theRoot == null) {
|
||||
throw new NullPointerException("Root type must be provided.");
|
||||
}
|
||||
this.yamlConstructors.put(null, new ConstructYamlObject());
|
||||
if (!Object.class.equals(theRoot.getType())) {
|
||||
rootTag = new Tag(theRoot.getType());
|
||||
}
|
||||
yamlClassConstructors.put(NodeId.scalar, new ConstructScalar());
|
||||
yamlClassConstructors.put(NodeId.mapping, new ConstructMapping());
|
||||
yamlClassConstructors.put(NodeId.sequence, new ConstructSequence());
|
||||
addTypeDescription(theRoot);
|
||||
if (moreTDs != null) {
|
||||
for (TypeDescription td : moreTDs) {
|
||||
addTypeDescription(td);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Constructor for a class which does not have to be in the classpath
|
||||
* or for a definition from a Spring ApplicationContext.
|
||||
*
|
||||
* @param theRoot
|
||||
* fully qualified class name of the root class (usually
|
||||
* JavaBean)
|
||||
* @throws ClassNotFoundException if cannot be loaded by the classloader
|
||||
*/
|
||||
public Constructor(String theRoot) throws ClassNotFoundException {
|
||||
this(Class.forName(check(theRoot)));
|
||||
}
|
||||
|
||||
private static final String check(String s) {
|
||||
if (s == null) {
|
||||
throw new NullPointerException("Root type must be provided.");
|
||||
}
|
||||
if (s.trim().length() == 0) {
|
||||
throw new YAMLException("Root type must be provided.");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct mapping instance (Map, JavaBean) when the runtime class is
|
||||
* known.
|
||||
*/
|
||||
protected class ConstructMapping implements Construct {
|
||||
|
||||
/**
|
||||
* Construct JavaBean. If type safe collections are used please look at
|
||||
* <code>TypeDescription</code>.
|
||||
*
|
||||
* @param node
|
||||
* node where the keys are property names (they can only be
|
||||
* <code>String</code>s) and values are objects to be created
|
||||
* @return constructed JavaBean
|
||||
*/
|
||||
public Object construct(Node node) {
|
||||
MappingNode mnode = (MappingNode) node;
|
||||
if (Map.class.isAssignableFrom(node.getType())) {
|
||||
if (node.isTwoStepsConstruction()) {
|
||||
return newMap(mnode);
|
||||
} else {
|
||||
return constructMapping(mnode);
|
||||
}
|
||||
} else if (Collection.class.isAssignableFrom(node.getType())) {
|
||||
if (node.isTwoStepsConstruction()) {
|
||||
return newSet(mnode);
|
||||
} else {
|
||||
return constructSet(mnode);
|
||||
}
|
||||
} else {
|
||||
Object obj = Constructor.this.newInstance(mnode);
|
||||
if (node.isTwoStepsConstruction()) {
|
||||
return obj;
|
||||
} else {
|
||||
return constructJavaBean2ndStep(mnode, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void construct2ndStep(Node node, Object object) {
|
||||
if (Map.class.isAssignableFrom(node.getType())) {
|
||||
constructMapping2ndStep((MappingNode) node, (Map<Object, Object>) object);
|
||||
} else if (Set.class.isAssignableFrom(node.getType())) {
|
||||
constructSet2ndStep((MappingNode) node, (Set<Object>) object);
|
||||
} else {
|
||||
constructJavaBean2ndStep((MappingNode) node, object);
|
||||
}
|
||||
}
|
||||
|
||||
// protected Object createEmptyJavaBean(MappingNode node) {
|
||||
// try {
|
||||
// Object instance = Constructor.this.newInstance(node);
|
||||
// if (instance != null) {
|
||||
// return instance;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Using only default constructor. Everything else will be
|
||||
// * initialized on 2nd step. If we do here some partial
|
||||
// * initialization, how do we then track what need to be done on
|
||||
// * 2nd step? I think it is better to get only object here (to
|
||||
// * have it as reference for recursion) and do all other thing on
|
||||
// * 2nd step.
|
||||
// */
|
||||
// java.lang.reflect.Constructor<?> c =
|
||||
// node.getType().getDeclaredConstructor();
|
||||
// c.setAccessible(true);
|
||||
// return c.newInstance();
|
||||
// } catch (Exception e) {
|
||||
// throw new YAMLException(e);
|
||||
// }
|
||||
// }
|
||||
|
||||
protected Object constructJavaBean2ndStep(MappingNode node, Object object) {
|
||||
flattenMapping(node);
|
||||
Class<? extends Object> beanType = node.getType();
|
||||
List<NodeTuple> nodeValue = node.getValue();
|
||||
for (NodeTuple tuple : nodeValue) {
|
||||
ScalarNode keyNode;
|
||||
if (tuple.getKeyNode() instanceof ScalarNode) {
|
||||
// key must be scalar
|
||||
keyNode = (ScalarNode) tuple.getKeyNode();
|
||||
} else {
|
||||
throw new YAMLException(
|
||||
"Keys must be scalars but found: " + tuple.getKeyNode());
|
||||
}
|
||||
Node valueNode = tuple.getValueNode();
|
||||
// keys can only be Strings
|
||||
keyNode.setType(String.class);
|
||||
String key = (String) constructObject(keyNode);
|
||||
try {
|
||||
TypeDescription memberDescription = typeDefinitions.get(beanType);
|
||||
Property property = memberDescription == null ? getProperty(beanType, key)
|
||||
: memberDescription.getProperty(key);
|
||||
|
||||
if (!property.isWritable()) {
|
||||
throw new YAMLException("No writable property '" + key + "' on class: "
|
||||
+ beanType.getName());
|
||||
}
|
||||
|
||||
valueNode.setType(property.getType());
|
||||
final boolean typeDetected = (memberDescription != null)
|
||||
? memberDescription.setupPropertyType(key, valueNode)
|
||||
: false;
|
||||
if (!typeDetected && valueNode.getNodeId() != NodeId.scalar) {
|
||||
// only if there is no explicit TypeDescription
|
||||
Class<?>[] arguments = property.getActualTypeArguments();
|
||||
if (arguments != null && arguments.length > 0) {
|
||||
// type safe (generic) collection may contain the
|
||||
// proper class
|
||||
if (valueNode.getNodeId() == NodeId.sequence) {
|
||||
Class<?> t = arguments[0];
|
||||
SequenceNode snode = (SequenceNode) valueNode;
|
||||
snode.setListType(t);
|
||||
} else if (Set.class.isAssignableFrom(valueNode.getType())) {
|
||||
Class<?> t = arguments[0];
|
||||
MappingNode mnode = (MappingNode) valueNode;
|
||||
mnode.setOnlyKeyType(t);
|
||||
mnode.setUseClassConstructor(true);
|
||||
} else if (Map.class.isAssignableFrom(valueNode.getType())) {
|
||||
Class<?> ketType = arguments[0];
|
||||
Class<?> valueType = arguments[1];
|
||||
MappingNode mnode = (MappingNode) valueNode;
|
||||
mnode.setTypes(ketType, valueType);
|
||||
mnode.setUseClassConstructor(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Object value = (memberDescription != null)
|
||||
? newInstance(memberDescription, key, valueNode)
|
||||
: constructObject(valueNode);
|
||||
// Correct when the property expects float but double was
|
||||
// constructed
|
||||
if (property.getType() == Float.TYPE || property.getType() == Float.class) {
|
||||
if (value instanceof Double) {
|
||||
value = ((Double) value).floatValue();
|
||||
}
|
||||
}
|
||||
// Correct when the property a String but the value is binary
|
||||
if (property.getType() == String.class && Tag.BINARY.equals(valueNode.getTag())
|
||||
&& value instanceof byte[]) {
|
||||
value = new String((byte[]) value);
|
||||
}
|
||||
|
||||
if (memberDescription == null
|
||||
|| !memberDescription.setProperty(object, key, value)) {
|
||||
property.set(object, value);
|
||||
}
|
||||
} catch (DuplicateKeyException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new ConstructorException(
|
||||
"Cannot create property=" + key + " for JavaBean=" + object,
|
||||
node.getStartMark(), e.getMessage(), valueNode.getStartMark(), e);
|
||||
}
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
private Object newInstance(TypeDescription memberDescription, String propertyName,
|
||||
Node node) {
|
||||
Object newInstance = memberDescription.newInstance(propertyName, node);
|
||||
if (newInstance != null) {
|
||||
constructedObjects.put(node, newInstance);
|
||||
return constructObjectNoCheck(node);
|
||||
}
|
||||
return constructObject(node);
|
||||
}
|
||||
|
||||
protected Property getProperty(Class<? extends Object> type, String name) {
|
||||
return getPropertyUtils().getProperty(type, name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an instance when the runtime class is not known but a global
|
||||
* tag with a class name is defined. It delegates the construction to the
|
||||
* appropriate constructor based on the node kind (scalar, sequence,
|
||||
* mapping)
|
||||
*/
|
||||
protected class ConstructYamlObject implements Construct {
|
||||
|
||||
private Construct getConstructor(Node node) {
|
||||
Class<?> cl = getClassForNode(node);
|
||||
node.setType(cl);
|
||||
// call the constructor as if the runtime class is defined
|
||||
Construct constructor = yamlClassConstructors.get(node.getNodeId());
|
||||
return constructor;
|
||||
}
|
||||
|
||||
public Object construct(Node node) {
|
||||
try {
|
||||
return getConstructor(node).construct(node);
|
||||
} catch (ConstructorException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new ConstructorException(null, null, "Can't construct a java object for "
|
||||
+ node.getTag() + "; exception=" + e.getMessage(), node.getStartMark(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public void construct2ndStep(Node node, Object object) {
|
||||
try {
|
||||
getConstructor(node).construct2ndStep(node, object);
|
||||
} catch (Exception e) {
|
||||
throw new ConstructorException(
|
||||
null, null, "Can't construct a second step for a java object for "
|
||||
+ node.getTag() + "; exception=" + e.getMessage(),
|
||||
node.getStartMark(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct scalar instance when the runtime class is known. Recursive
|
||||
* structures are not supported.
|
||||
*/
|
||||
protected class ConstructScalar extends AbstractConstruct {
|
||||
public Object construct(Node nnode) {
|
||||
ScalarNode node = (ScalarNode) nnode;
|
||||
Class<?> type = node.getType();
|
||||
|
||||
try {
|
||||
return newInstance(type, node, false);
|
||||
} catch (InstantiationException e1) {
|
||||
}
|
||||
|
||||
Object result;
|
||||
if (type.isPrimitive() || type == String.class || Number.class.isAssignableFrom(type)
|
||||
|| type == Boolean.class || Date.class.isAssignableFrom(type)
|
||||
|| type == Character.class || type == BigInteger.class
|
||||
|| type == BigDecimal.class || Enum.class.isAssignableFrom(type)
|
||||
|| Tag.BINARY.equals(node.getTag()) || Calendar.class.isAssignableFrom(type)
|
||||
|| type == UUID.class) {
|
||||
// standard classes created directly
|
||||
result = constructStandardJavaInstance(type, node);
|
||||
} else {
|
||||
// there must be only 1 constructor with 1 argument
|
||||
java.lang.reflect.Constructor<?>[] javaConstructors = type
|
||||
.getDeclaredConstructors();
|
||||
int oneArgCount = 0;
|
||||
java.lang.reflect.Constructor<?> javaConstructor = null;
|
||||
for (java.lang.reflect.Constructor<?> c : javaConstructors) {
|
||||
if (c.getParameterTypes().length == 1) {
|
||||
oneArgCount++;
|
||||
javaConstructor = c;
|
||||
}
|
||||
}
|
||||
Object argument;
|
||||
if (javaConstructor == null) {
|
||||
try {
|
||||
return newInstance(type, node, false);
|
||||
} catch (InstantiationException ie) {
|
||||
throw new YAMLException("No single argument constructor found for " + type
|
||||
+ " : " + ie.getMessage());
|
||||
}
|
||||
} else if (oneArgCount == 1) {
|
||||
argument = constructStandardJavaInstance(javaConstructor.getParameterTypes()[0],
|
||||
node);
|
||||
} else {
|
||||
// TODO it should be possible to use implicit types instead
|
||||
// of forcing String. Resolver must be available here to
|
||||
// obtain the implicit tag. Then we can set the tag and call
|
||||
// callConstructor(node) to create the argument instance.
|
||||
// On the other hand it may be safer to require a custom
|
||||
// constructor to avoid guessing the argument class
|
||||
argument = constructScalar(node);
|
||||
try {
|
||||
javaConstructor = type.getDeclaredConstructor(String.class);
|
||||
} catch (Exception e) {
|
||||
throw new YAMLException("Can't construct a java object for scalar "
|
||||
+ node.getTag() + "; No String constructor found. Exception="
|
||||
+ e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
javaConstructor.setAccessible(true);
|
||||
result = javaConstructor.newInstance(argument);
|
||||
} catch (Exception e) {
|
||||
throw new ConstructorException(null, null,
|
||||
"Can't construct a java object for scalar " + node.getTag()
|
||||
+ "; exception=" + e.getMessage(),
|
||||
node.getStartMark(), e);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Object constructStandardJavaInstance(@SuppressWarnings("rawtypes") Class type,
|
||||
ScalarNode node) {
|
||||
Object result;
|
||||
if (type == String.class) {
|
||||
Construct stringConstructor = yamlConstructors.get(Tag.STR);
|
||||
result = stringConstructor.construct(node);
|
||||
} else if (type == Boolean.class || type == Boolean.TYPE) {
|
||||
Construct boolConstructor = yamlConstructors.get(Tag.BOOL);
|
||||
result = boolConstructor.construct(node);
|
||||
} else if (type == Character.class || type == Character.TYPE) {
|
||||
Construct charConstructor = yamlConstructors.get(Tag.STR);
|
||||
String ch = (String) charConstructor.construct(node);
|
||||
if (ch.length() == 0) {
|
||||
result = null;
|
||||
} else if (ch.length() != 1) {
|
||||
throw new YAMLException(
|
||||
"Invalid node Character: '" + ch + "'; length: " + ch.length());
|
||||
} else {
|
||||
result = Character.valueOf(ch.charAt(0));
|
||||
}
|
||||
} else if (Date.class.isAssignableFrom(type)) {
|
||||
Construct dateConstructor = yamlConstructors.get(Tag.TIMESTAMP);
|
||||
Date date = (Date) dateConstructor.construct(node);
|
||||
if (type == Date.class) {
|
||||
result = date;
|
||||
} else {
|
||||
try {
|
||||
java.lang.reflect.Constructor<?> constr = type.getConstructor(long.class);
|
||||
result = constr.newInstance(date.getTime());
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new YAMLException("Cannot construct: '" + type + "'");
|
||||
}
|
||||
}
|
||||
} else if (type == Float.class || type == Double.class || type == Float.TYPE
|
||||
|| type == Double.TYPE || type == BigDecimal.class) {
|
||||
if (type == BigDecimal.class) {
|
||||
result = new BigDecimal(node.getValue());
|
||||
} else {
|
||||
Construct doubleConstructor = yamlConstructors.get(Tag.FLOAT);
|
||||
result = doubleConstructor.construct(node);
|
||||
if (type == Float.class || type == Float.TYPE) {
|
||||
result = Float.valueOf(((Double) result).floatValue());
|
||||
}
|
||||
}
|
||||
} else if (type == Byte.class || type == Short.class || type == Integer.class
|
||||
|| type == Long.class || type == BigInteger.class || type == Byte.TYPE
|
||||
|| type == Short.TYPE || type == Integer.TYPE || type == Long.TYPE) {
|
||||
Construct intConstructor = yamlConstructors.get(Tag.INT);
|
||||
result = intConstructor.construct(node);
|
||||
if (type == Byte.class || type == Byte.TYPE) {
|
||||
result = Byte.valueOf(result.toString());
|
||||
} else if (type == Short.class || type == Short.TYPE) {
|
||||
result = Short.valueOf(result.toString());
|
||||
} else if (type == Integer.class || type == Integer.TYPE) {
|
||||
result = Integer.parseInt(result.toString());
|
||||
} else if (type == Long.class || type == Long.TYPE) {
|
||||
result = Long.valueOf(result.toString());
|
||||
} else {
|
||||
// only BigInteger left
|
||||
result = new BigInteger(result.toString());
|
||||
}
|
||||
} else if (Enum.class.isAssignableFrom(type)) {
|
||||
String enumValueName = node.getValue();
|
||||
try {
|
||||
result = Enum.valueOf(type, enumValueName);
|
||||
} catch (Exception ex) {
|
||||
throw new YAMLException("Unable to find enum value '" + enumValueName
|
||||
+ "' for enum class: " + type.getName());
|
||||
}
|
||||
} else if (Calendar.class.isAssignableFrom(type)) {
|
||||
ConstructYamlTimestamp contr = new ConstructYamlTimestamp();
|
||||
contr.construct(node);
|
||||
result = contr.getCalendar();
|
||||
} else if (Number.class.isAssignableFrom(type)) {
|
||||
//since we do not know the exact type we create Float
|
||||
ConstructYamlFloat contr = new ConstructYamlFloat();
|
||||
result = contr.construct(node);
|
||||
} else if (UUID.class == type) {
|
||||
result = UUID.fromString(node.getValue());
|
||||
} else {
|
||||
if (yamlConstructors.containsKey(node.getTag())) {
|
||||
result = yamlConstructors.get(node.getTag()).construct(node);
|
||||
} else {
|
||||
throw new YAMLException("Unsupported class: " + type);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct sequence (List, Array, or immutable object) when the runtime
|
||||
* class is known.
|
||||
*/
|
||||
protected class ConstructSequence implements Construct {
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object construct(Node node) {
|
||||
SequenceNode snode = (SequenceNode) node;
|
||||
if (Set.class.isAssignableFrom(node.getType())) {
|
||||
if (node.isTwoStepsConstruction()) {
|
||||
throw new YAMLException("Set cannot be recursive.");
|
||||
} else {
|
||||
return constructSet(snode);
|
||||
}
|
||||
} else if (Collection.class.isAssignableFrom(node.getType())) {
|
||||
if (node.isTwoStepsConstruction()) {
|
||||
return newList(snode);
|
||||
} else {
|
||||
return constructSequence(snode);
|
||||
}
|
||||
} else if (node.getType().isArray()) {
|
||||
if (node.isTwoStepsConstruction()) {
|
||||
return createArray(node.getType(), snode.getValue().size());
|
||||
} else {
|
||||
return constructArray(snode);
|
||||
}
|
||||
} else {
|
||||
// create immutable object
|
||||
List<java.lang.reflect.Constructor<?>> possibleConstructors = new ArrayList<java.lang.reflect.Constructor<?>>(
|
||||
snode.getValue().size());
|
||||
for (java.lang.reflect.Constructor<?> constructor : node.getType()
|
||||
.getDeclaredConstructors()) {
|
||||
if (snode.getValue().size() == constructor.getParameterTypes().length) {
|
||||
possibleConstructors.add(constructor);
|
||||
}
|
||||
}
|
||||
if (!possibleConstructors.isEmpty()) {
|
||||
if (possibleConstructors.size() == 1) {
|
||||
Object[] argumentList = new Object[snode.getValue().size()];
|
||||
java.lang.reflect.Constructor<?> c = possibleConstructors.get(0);
|
||||
int index = 0;
|
||||
for (Node argumentNode : snode.getValue()) {
|
||||
Class<?> type = c.getParameterTypes()[index];
|
||||
// set runtime classes for arguments
|
||||
argumentNode.setType(type);
|
||||
argumentList[index++] = constructObject(argumentNode);
|
||||
}
|
||||
|
||||
try {
|
||||
c.setAccessible(true);
|
||||
return c.newInstance(argumentList);
|
||||
} catch (Exception e) {
|
||||
throw new YAMLException(e);
|
||||
}
|
||||
}
|
||||
|
||||
// use BaseConstructor
|
||||
List<Object> argumentList = (List<Object>) constructSequence(snode);
|
||||
Class<?>[] parameterTypes = new Class[argumentList.size()];
|
||||
int index = 0;
|
||||
for (Object parameter : argumentList) {
|
||||
parameterTypes[index] = parameter.getClass();
|
||||
index++;
|
||||
}
|
||||
|
||||
for (java.lang.reflect.Constructor<?> c : possibleConstructors) {
|
||||
Class<?>[] argTypes = c.getParameterTypes();
|
||||
boolean foundConstructor = true;
|
||||
for (int i = 0; i < argTypes.length; i++) {
|
||||
if (!wrapIfPrimitive(argTypes[i]).isAssignableFrom(parameterTypes[i])) {
|
||||
foundConstructor = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (foundConstructor) {
|
||||
try {
|
||||
c.setAccessible(true);
|
||||
return c.newInstance(argumentList.toArray());
|
||||
} catch (Exception e) {
|
||||
throw new YAMLException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new YAMLException(
|
||||
"No suitable constructor with " + String.valueOf(snode.getValue().size())
|
||||
+ " arguments found for " + node.getType());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private final Class<? extends Object> wrapIfPrimitive(Class<?> clazz) {
|
||||
if (!clazz.isPrimitive()) {
|
||||
return clazz;
|
||||
}
|
||||
if (clazz == Integer.TYPE) {
|
||||
return Integer.class;
|
||||
}
|
||||
if (clazz == Float.TYPE) {
|
||||
return Float.class;
|
||||
}
|
||||
if (clazz == Double.TYPE) {
|
||||
return Double.class;
|
||||
}
|
||||
if (clazz == Boolean.TYPE) {
|
||||
return Boolean.class;
|
||||
}
|
||||
if (clazz == Long.TYPE) {
|
||||
return Long.class;
|
||||
}
|
||||
if (clazz == Character.TYPE) {
|
||||
return Character.class;
|
||||
}
|
||||
if (clazz == Short.TYPE) {
|
||||
return Short.class;
|
||||
}
|
||||
if (clazz == Byte.TYPE) {
|
||||
return Byte.class;
|
||||
}
|
||||
throw new YAMLException("Unexpected primitive " + clazz);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void construct2ndStep(Node node, Object object) {
|
||||
SequenceNode snode = (SequenceNode) node;
|
||||
if (List.class.isAssignableFrom(node.getType())) {
|
||||
List<Object> list = (List<Object>) object;
|
||||
constructSequenceStep2(snode, list);
|
||||
} else if (node.getType().isArray()) {
|
||||
constructArrayStep2(snode, object);
|
||||
} else {
|
||||
throw new YAMLException("Immutable objects cannot be recursive.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Class<?> getClassForNode(Node node) {
|
||||
Class<? extends Object> classForTag = typeTags.get(node.getTag());
|
||||
if (classForTag == null) {
|
||||
String name = node.getTag().getClassName();
|
||||
Class<?> cl;
|
||||
try {
|
||||
cl = getClassForName(name);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new YAMLException("Class not found: " + name);
|
||||
}
|
||||
typeTags.put(node.getTag(), cl);
|
||||
return cl;
|
||||
} else {
|
||||
return classForTag;
|
||||
}
|
||||
}
|
||||
|
||||
protected Class<?> getClassForName(String name) throws ClassNotFoundException {
|
||||
try {
|
||||
return Class.forName(name, true, Thread.currentThread().getContextClassLoader());
|
||||
} catch (ClassNotFoundException e) {
|
||||
return Class.forName(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.constructor;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.MarkedYAMLException;
|
||||
|
||||
public class ConstructorException extends MarkedYAMLException {
|
||||
private static final long serialVersionUID = -8816339931365239910L;
|
||||
|
||||
protected ConstructorException(String context, Mark contextMark, String problem,
|
||||
Mark problemMark, Throwable cause) {
|
||||
super(context, contextMark, problem, problemMark, cause);
|
||||
}
|
||||
|
||||
protected ConstructorException(String context, Mark contextMark, String problem,
|
||||
Mark problemMark) {
|
||||
this(context, contextMark, problem, problemMark, null);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.constructor;
|
||||
|
||||
/**
|
||||
* Construct instances with a custom Class Loader.
|
||||
*/
|
||||
public class CustomClassLoaderConstructor extends Constructor {
|
||||
private ClassLoader loader = CustomClassLoaderConstructor.class.getClassLoader();
|
||||
|
||||
public CustomClassLoaderConstructor(ClassLoader cLoader) {
|
||||
this(Object.class, cLoader);
|
||||
}
|
||||
|
||||
public CustomClassLoaderConstructor(Class<? extends Object> theRoot, ClassLoader theLoader) {
|
||||
super(theRoot);
|
||||
if (theLoader == null) {
|
||||
throw new NullPointerException("Loader must be provided.");
|
||||
}
|
||||
this.loader = theLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getClassForName(String name) throws ClassNotFoundException {
|
||||
return Class.forName(name, true, loader);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.constructor;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
public class DuplicateKeyException extends ConstructorException {
|
||||
|
||||
protected DuplicateKeyException(Mark contextMark, Object key,
|
||||
Mark problemMark) {
|
||||
super("while constructing a mapping", contextMark, "found duplicate key " + key.toString(), problemMark);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,544 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.constructor;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.TreeSet;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.YAMLException;
|
||||
import io.jenkins.plugins.casc.snakeyaml.external.biz.base64Coder.Base64Coder;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.MappingNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Node;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.NodeId;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.NodeTuple;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.ScalarNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.SequenceNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Tag;
|
||||
|
||||
/**
|
||||
* Construct standard Java classes
|
||||
*/
|
||||
public class SafeConstructor extends BaseConstructor {
|
||||
|
||||
public static final ConstructUndefined undefinedConstructor = new ConstructUndefined();
|
||||
|
||||
public SafeConstructor() {
|
||||
this.yamlConstructors.put(Tag.NULL, new ConstructYamlNull());
|
||||
this.yamlConstructors.put(Tag.BOOL, new ConstructYamlBool());
|
||||
this.yamlConstructors.put(Tag.INT, new ConstructYamlInt());
|
||||
this.yamlConstructors.put(Tag.FLOAT, new ConstructYamlFloat());
|
||||
this.yamlConstructors.put(Tag.BINARY, new ConstructYamlBinary());
|
||||
this.yamlConstructors.put(Tag.TIMESTAMP, new ConstructYamlTimestamp());
|
||||
this.yamlConstructors.put(Tag.OMAP, new ConstructYamlOmap());
|
||||
this.yamlConstructors.put(Tag.PAIRS, new ConstructYamlPairs());
|
||||
this.yamlConstructors.put(Tag.SET, new ConstructYamlSet());
|
||||
this.yamlConstructors.put(Tag.STR, new ConstructYamlStr());
|
||||
this.yamlConstructors.put(Tag.SEQ, new ConstructYamlSeq());
|
||||
this.yamlConstructors.put(Tag.MAP, new ConstructYamlMap());
|
||||
this.yamlConstructors.put(null, undefinedConstructor);
|
||||
this.yamlClassConstructors.put(NodeId.scalar, undefinedConstructor);
|
||||
this.yamlClassConstructors.put(NodeId.sequence, undefinedConstructor);
|
||||
this.yamlClassConstructors.put(NodeId.mapping, undefinedConstructor);
|
||||
}
|
||||
|
||||
protected void flattenMapping(MappingNode node) {
|
||||
// perform merging only on nodes containing merge node(s)
|
||||
processDuplicateKeys(node);
|
||||
if (node.isMerged()) {
|
||||
node.setValue(mergeNode(node, true, new HashMap<Object, Integer>(),
|
||||
new ArrayList<NodeTuple>()));
|
||||
}
|
||||
}
|
||||
|
||||
protected void processDuplicateKeys(MappingNode node) {
|
||||
List<NodeTuple> nodeValue = node.getValue();
|
||||
Map<Object, Integer> keys = new HashMap<Object, Integer>(nodeValue.size());
|
||||
TreeSet<Integer> toRemove = new TreeSet<Integer>();
|
||||
int i = 0;
|
||||
for (NodeTuple tuple : nodeValue) {
|
||||
Node keyNode = tuple.getKeyNode();
|
||||
if (!keyNode.getTag().equals(Tag.MERGE)) {
|
||||
Object key = constructObject(keyNode);
|
||||
if (key != null) {
|
||||
try {
|
||||
key.hashCode();// check circular dependencies
|
||||
} catch (Exception e) {
|
||||
throw new ConstructorException("while constructing a mapping",
|
||||
node.getStartMark(), "found unacceptable key " + key,
|
||||
tuple.getKeyNode().getStartMark(), e);
|
||||
}
|
||||
}
|
||||
|
||||
Integer prevIndex = keys.put(key, i);
|
||||
if (prevIndex != null) {
|
||||
if (!isAllowDuplicateKeys()) {
|
||||
throw new DuplicateKeyException(node.getStartMark(), key,
|
||||
tuple.getKeyNode().getStartMark());
|
||||
}
|
||||
toRemove.add(prevIndex);
|
||||
}
|
||||
}
|
||||
i = i + 1;
|
||||
}
|
||||
|
||||
Iterator<Integer> indicies2remove = toRemove.descendingIterator();
|
||||
while (indicies2remove.hasNext()) {
|
||||
nodeValue.remove(indicies2remove.next().intValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does merge for supplied mapping node.
|
||||
*
|
||||
* @param node
|
||||
* where to merge
|
||||
* @param isPreffered
|
||||
* true if keys of node should take precedence over others...
|
||||
* @param key2index
|
||||
* maps already merged keys to index from values
|
||||
* @param values
|
||||
* collects merged NodeTuple
|
||||
* @return list of the merged NodeTuple (to be set as value for the
|
||||
* MappingNode)
|
||||
*/
|
||||
private List<NodeTuple> mergeNode(MappingNode node, boolean isPreffered,
|
||||
Map<Object, Integer> key2index, List<NodeTuple> values) {
|
||||
Iterator<NodeTuple> iter = node.getValue().iterator();
|
||||
while (iter.hasNext()) {
|
||||
final NodeTuple nodeTuple = iter.next();
|
||||
final Node keyNode = nodeTuple.getKeyNode();
|
||||
final Node valueNode = nodeTuple.getValueNode();
|
||||
if (keyNode.getTag().equals(Tag.MERGE)) {
|
||||
iter.remove();
|
||||
switch (valueNode.getNodeId()) {
|
||||
case mapping:
|
||||
MappingNode mn = (MappingNode) valueNode;
|
||||
mergeNode(mn, false, key2index, values);
|
||||
break;
|
||||
case sequence:
|
||||
SequenceNode sn = (SequenceNode) valueNode;
|
||||
List<Node> vals = sn.getValue();
|
||||
for (Node subnode : vals) {
|
||||
if (!(subnode instanceof MappingNode)) {
|
||||
throw new ConstructorException("while constructing a mapping",
|
||||
node.getStartMark(),
|
||||
"expected a mapping for merging, but found "
|
||||
+ subnode.getNodeId(),
|
||||
subnode.getStartMark());
|
||||
}
|
||||
MappingNode mnode = (MappingNode) subnode;
|
||||
mergeNode(mnode, false, key2index, values);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new ConstructorException("while constructing a mapping",
|
||||
node.getStartMark(),
|
||||
"expected a mapping or list of mappings for merging, but found "
|
||||
+ valueNode.getNodeId(),
|
||||
valueNode.getStartMark());
|
||||
}
|
||||
} else {
|
||||
// we need to construct keys to avoid duplications
|
||||
Object key = constructObject(keyNode);
|
||||
if (!key2index.containsKey(key)) { // 1st time merging key
|
||||
values.add(nodeTuple);
|
||||
// keep track where tuple for the key is
|
||||
key2index.put(key, values.size() - 1);
|
||||
} else if (isPreffered) { // there is value for the key, but we
|
||||
// need to override it
|
||||
// change value for the key using saved position
|
||||
values.set(key2index.get(key), nodeTuple);
|
||||
}
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void constructMapping2ndStep(MappingNode node, Map<Object, Object> mapping) {
|
||||
flattenMapping(node);
|
||||
super.constructMapping2ndStep(node, mapping);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void constructSet2ndStep(MappingNode node, Set<Object> set) {
|
||||
flattenMapping(node);
|
||||
super.constructSet2ndStep(node, set);
|
||||
}
|
||||
|
||||
public class ConstructYamlNull extends AbstractConstruct {
|
||||
@Override
|
||||
public Object construct(Node node) {
|
||||
constructScalar((ScalarNode) node);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private final static Map<String, Boolean> BOOL_VALUES = new HashMap<String, Boolean>();
|
||||
static {
|
||||
BOOL_VALUES.put("yes", Boolean.TRUE);
|
||||
BOOL_VALUES.put("no", Boolean.FALSE);
|
||||
BOOL_VALUES.put("true", Boolean.TRUE);
|
||||
BOOL_VALUES.put("false", Boolean.FALSE);
|
||||
BOOL_VALUES.put("on", Boolean.TRUE);
|
||||
BOOL_VALUES.put("off", Boolean.FALSE);
|
||||
}
|
||||
|
||||
public class ConstructYamlBool extends AbstractConstruct {
|
||||
@Override
|
||||
public Object construct(Node node) {
|
||||
String val = (String) constructScalar((ScalarNode) node);
|
||||
return BOOL_VALUES.get(val.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
public class ConstructYamlInt extends AbstractConstruct {
|
||||
@Override
|
||||
public Object construct(Node node) {
|
||||
String value = constructScalar((ScalarNode) node).toString().replaceAll("_", "");
|
||||
int sign = +1;
|
||||
char first = value.charAt(0);
|
||||
if (first == '-') {
|
||||
sign = -1;
|
||||
value = value.substring(1);
|
||||
} else if (first == '+') {
|
||||
value = value.substring(1);
|
||||
}
|
||||
int base = 10;
|
||||
if ("0".equals(value)) {
|
||||
return Integer.valueOf(0);
|
||||
} else if (value.startsWith("0b")) {
|
||||
value = value.substring(2);
|
||||
base = 2;
|
||||
} else if (value.startsWith("0x")) {
|
||||
value = value.substring(2);
|
||||
base = 16;
|
||||
} else if (value.startsWith("0")) {
|
||||
value = value.substring(1);
|
||||
base = 8;
|
||||
} else if (value.indexOf(':') != -1) {
|
||||
String[] digits = value.split(":");
|
||||
int bes = 1;
|
||||
int val = 0;
|
||||
for (int i = 0, j = digits.length; i < j; i++) {
|
||||
val += Long.parseLong(digits[j - i - 1]) * bes;
|
||||
bes *= 60;
|
||||
}
|
||||
return createNumber(sign, String.valueOf(val), 10);
|
||||
} else {
|
||||
return createNumber(sign, value, 10);
|
||||
}
|
||||
return createNumber(sign, value, base);
|
||||
}
|
||||
}
|
||||
|
||||
private Number createNumber(int sign, String number, int radix) {
|
||||
Number result;
|
||||
if (sign < 0) {
|
||||
number = "-" + number;
|
||||
}
|
||||
try {
|
||||
result = Integer.valueOf(number, radix);
|
||||
} catch (NumberFormatException e) {
|
||||
try {
|
||||
result = Long.valueOf(number, radix);
|
||||
} catch (NumberFormatException e1) {
|
||||
result = new BigInteger(number, radix);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public class ConstructYamlFloat extends AbstractConstruct {
|
||||
@Override
|
||||
public Object construct(Node node) {
|
||||
String value = constructScalar((ScalarNode) node).toString().replaceAll("_", "");
|
||||
int sign = +1;
|
||||
char first = value.charAt(0);
|
||||
if (first == '-') {
|
||||
sign = -1;
|
||||
value = value.substring(1);
|
||||
} else if (first == '+') {
|
||||
value = value.substring(1);
|
||||
}
|
||||
String valLower = value.toLowerCase();
|
||||
if (".inf".equals(valLower)) {
|
||||
return Double
|
||||
.valueOf(sign == -1 ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY);
|
||||
} else if (".nan".equals(valLower)) {
|
||||
return Double.valueOf(Double.NaN);
|
||||
} else if (value.indexOf(':') != -1) {
|
||||
String[] digits = value.split(":");
|
||||
int bes = 1;
|
||||
double val = 0.0;
|
||||
for (int i = 0, j = digits.length; i < j; i++) {
|
||||
val += Double.parseDouble(digits[j - i - 1]) * bes;
|
||||
bes *= 60;
|
||||
}
|
||||
return Double.valueOf(sign * val);
|
||||
} else {
|
||||
Double d = Double.valueOf(value);
|
||||
return Double.valueOf(d.doubleValue() * sign);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ConstructYamlBinary extends AbstractConstruct {
|
||||
@Override
|
||||
public Object construct(Node node) {
|
||||
// Ignore white spaces for base64 encoded scalar
|
||||
String noWhiteSpaces = constructScalar((ScalarNode) node).toString().replaceAll("\\s",
|
||||
"");
|
||||
byte[] decoded = Base64Coder.decode(noWhiteSpaces.toCharArray());
|
||||
return decoded;
|
||||
}
|
||||
}
|
||||
|
||||
private final static Pattern TIMESTAMP_REGEXP = Pattern.compile(
|
||||
"^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:(?:[Tt]|[ \t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \t]*(?:Z|([-+][0-9][0-9]?)(?::([0-9][0-9])?)?))?)?$");
|
||||
private final static Pattern YMD_REGEXP = Pattern
|
||||
.compile("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)$");
|
||||
|
||||
public static class ConstructYamlTimestamp extends AbstractConstruct {
|
||||
private Calendar calendar;
|
||||
|
||||
public Calendar getCalendar() {
|
||||
return calendar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object construct(Node node) {
|
||||
ScalarNode scalar = (ScalarNode) node;
|
||||
String nodeValue = scalar.getValue();
|
||||
Matcher match = YMD_REGEXP.matcher(nodeValue);
|
||||
if (match.matches()) {
|
||||
String year_s = match.group(1);
|
||||
String month_s = match.group(2);
|
||||
String day_s = match.group(3);
|
||||
calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
|
||||
calendar.clear();
|
||||
calendar.set(Calendar.YEAR, Integer.parseInt(year_s));
|
||||
// Java's months are zero-based...
|
||||
calendar.set(Calendar.MONTH, Integer.parseInt(month_s) - 1); // x
|
||||
calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(day_s));
|
||||
return calendar.getTime();
|
||||
} else {
|
||||
match = TIMESTAMP_REGEXP.matcher(nodeValue);
|
||||
if (!match.matches()) {
|
||||
throw new YAMLException("Unexpected timestamp: " + nodeValue);
|
||||
}
|
||||
String year_s = match.group(1);
|
||||
String month_s = match.group(2);
|
||||
String day_s = match.group(3);
|
||||
String hour_s = match.group(4);
|
||||
String min_s = match.group(5);
|
||||
// seconds and milliseconds
|
||||
String seconds = match.group(6);
|
||||
String millis = match.group(7);
|
||||
if (millis != null) {
|
||||
seconds = seconds + "." + millis;
|
||||
}
|
||||
double fractions = Double.parseDouble(seconds);
|
||||
int sec_s = (int) Math.round(Math.floor(fractions));
|
||||
int usec = (int) Math.round((fractions - sec_s) * 1000);
|
||||
// timezone
|
||||
String timezoneh_s = match.group(8);
|
||||
String timezonem_s = match.group(9);
|
||||
TimeZone timeZone;
|
||||
if (timezoneh_s != null) {
|
||||
String time = timezonem_s != null ? ":" + timezonem_s : "00";
|
||||
timeZone = TimeZone.getTimeZone("GMT" + timezoneh_s + time);
|
||||
} else {
|
||||
// no time zone provided
|
||||
timeZone = TimeZone.getTimeZone("UTC");
|
||||
}
|
||||
calendar = Calendar.getInstance(timeZone);
|
||||
calendar.set(Calendar.YEAR, Integer.parseInt(year_s));
|
||||
// Java's months are zero-based...
|
||||
calendar.set(Calendar.MONTH, Integer.parseInt(month_s) - 1);
|
||||
calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(day_s));
|
||||
calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hour_s));
|
||||
calendar.set(Calendar.MINUTE, Integer.parseInt(min_s));
|
||||
calendar.set(Calendar.SECOND, sec_s);
|
||||
calendar.set(Calendar.MILLISECOND, usec);
|
||||
return calendar.getTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ConstructYamlOmap extends AbstractConstruct {
|
||||
@Override
|
||||
public Object construct(Node node) {
|
||||
// Note: we do not check for duplicate keys, because it's too
|
||||
// CPU-expensive.
|
||||
Map<Object, Object> omap = new LinkedHashMap<Object, Object>();
|
||||
if (!(node instanceof SequenceNode)) {
|
||||
throw new ConstructorException("while constructing an ordered map",
|
||||
node.getStartMark(), "expected a sequence, but found " + node.getNodeId(),
|
||||
node.getStartMark());
|
||||
}
|
||||
SequenceNode snode = (SequenceNode) node;
|
||||
for (Node subnode : snode.getValue()) {
|
||||
if (!(subnode instanceof MappingNode)) {
|
||||
throw new ConstructorException("while constructing an ordered map",
|
||||
node.getStartMark(),
|
||||
"expected a mapping of length 1, but found " + subnode.getNodeId(),
|
||||
subnode.getStartMark());
|
||||
}
|
||||
MappingNode mnode = (MappingNode) subnode;
|
||||
if (mnode.getValue().size() != 1) {
|
||||
throw new ConstructorException("while constructing an ordered map",
|
||||
node.getStartMark(), "expected a single mapping item, but found "
|
||||
+ mnode.getValue().size() + " items",
|
||||
mnode.getStartMark());
|
||||
}
|
||||
Node keyNode = mnode.getValue().get(0).getKeyNode();
|
||||
Node valueNode = mnode.getValue().get(0).getValueNode();
|
||||
Object key = constructObject(keyNode);
|
||||
Object value = constructObject(valueNode);
|
||||
omap.put(key, value);
|
||||
}
|
||||
return omap;
|
||||
}
|
||||
}
|
||||
|
||||
public class ConstructYamlPairs extends AbstractConstruct {
|
||||
@Override
|
||||
public Object construct(Node node) {
|
||||
// Note: we do not check for duplicate keys, because it's too
|
||||
// CPU-expensive.
|
||||
if (!(node instanceof SequenceNode)) {
|
||||
throw new ConstructorException("while constructing pairs", node.getStartMark(),
|
||||
"expected a sequence, but found " + node.getNodeId(), node.getStartMark());
|
||||
}
|
||||
SequenceNode snode = (SequenceNode) node;
|
||||
List<Object[]> pairs = new ArrayList<Object[]>(snode.getValue().size());
|
||||
for (Node subnode : snode.getValue()) {
|
||||
if (!(subnode instanceof MappingNode)) {
|
||||
throw new ConstructorException("while constructingpairs", node.getStartMark(),
|
||||
"expected a mapping of length 1, but found " + subnode.getNodeId(),
|
||||
subnode.getStartMark());
|
||||
}
|
||||
MappingNode mnode = (MappingNode) subnode;
|
||||
if (mnode.getValue().size() != 1) {
|
||||
throw new ConstructorException("while constructing pairs", node.getStartMark(),
|
||||
"expected a single mapping item, but found " + mnode.getValue().size()
|
||||
+ " items",
|
||||
mnode.getStartMark());
|
||||
}
|
||||
Node keyNode = mnode.getValue().get(0).getKeyNode();
|
||||
Node valueNode = mnode.getValue().get(0).getValueNode();
|
||||
Object key = constructObject(keyNode);
|
||||
Object value = constructObject(valueNode);
|
||||
pairs.add(new Object[] { key, value });
|
||||
}
|
||||
return pairs;
|
||||
}
|
||||
}
|
||||
|
||||
public class ConstructYamlSet implements Construct {
|
||||
@Override
|
||||
public Object construct(Node node) {
|
||||
if (node.isTwoStepsConstruction()) {
|
||||
return (constructedObjects.containsKey(node) ? constructedObjects.get(node)
|
||||
: createDefaultSet(((MappingNode) node).getValue().size()));
|
||||
} else {
|
||||
return constructSet((MappingNode) node);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void construct2ndStep(Node node, Object object) {
|
||||
if (node.isTwoStepsConstruction()) {
|
||||
constructSet2ndStep((MappingNode) node, (Set<Object>) object);
|
||||
} else {
|
||||
throw new YAMLException("Unexpected recursive set structure. Node: " + node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ConstructYamlStr extends AbstractConstruct {
|
||||
@Override
|
||||
public Object construct(Node node) {
|
||||
return constructScalar((ScalarNode) node);
|
||||
}
|
||||
}
|
||||
|
||||
public class ConstructYamlSeq implements Construct {
|
||||
@Override
|
||||
public Object construct(Node node) {
|
||||
SequenceNode seqNode = (SequenceNode) node;
|
||||
if (node.isTwoStepsConstruction()) {
|
||||
return newList(seqNode);
|
||||
} else {
|
||||
return constructSequence(seqNode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void construct2ndStep(Node node, Object data) {
|
||||
if (node.isTwoStepsConstruction()) {
|
||||
constructSequenceStep2((SequenceNode) node, (List<Object>) data);
|
||||
} else {
|
||||
throw new YAMLException("Unexpected recursive sequence structure. Node: " + node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ConstructYamlMap implements Construct {
|
||||
@Override
|
||||
public Object construct(Node node) {
|
||||
MappingNode mnode = (MappingNode) node;
|
||||
if (node.isTwoStepsConstruction()) {
|
||||
return createDefaultMap(mnode.getValue().size());
|
||||
} else {
|
||||
return constructMapping(mnode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void construct2ndStep(Node node, Object object) {
|
||||
if (node.isTwoStepsConstruction()) {
|
||||
constructMapping2ndStep((MappingNode) node, (Map<Object, Object>) object);
|
||||
} else {
|
||||
throw new YAMLException("Unexpected recursive mapping structure. Node: " + node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ConstructUndefined extends AbstractConstruct {
|
||||
@Override
|
||||
public Object construct(Node node) {
|
||||
throw new ConstructorException(null, null,
|
||||
"could not determine a constructor for the tag " + node.getTag(),
|
||||
node.getStartMark());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.emitter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.Event;
|
||||
|
||||
public interface Emitable {
|
||||
void emit(Event event) throws IOException;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.emitter;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.YAMLException;
|
||||
|
||||
public class EmitterException extends YAMLException {
|
||||
private static final long serialVersionUID = -8280070025452995908L;
|
||||
|
||||
public EmitterException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.emitter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Python's methods are first class object. Java needs a class.
|
||||
*/
|
||||
interface EmitterState {
|
||||
void expect() throws IOException;
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.emitter;
|
||||
|
||||
public final class ScalarAnalysis {
|
||||
public String scalar;
|
||||
public boolean empty;
|
||||
public boolean multiline;
|
||||
public boolean allowFlowPlain;
|
||||
public boolean allowBlockPlain;
|
||||
public boolean allowSingleQuoted;
|
||||
public boolean allowBlock;
|
||||
|
||||
public ScalarAnalysis(String scalar, boolean empty, boolean multiline, boolean allowFlowPlain,
|
||||
boolean allowBlockPlain, boolean allowSingleQuoted, boolean allowBlock) {
|
||||
this.scalar = scalar;
|
||||
this.empty = empty;
|
||||
this.multiline = multiline;
|
||||
this.allowFlowPlain = allowFlowPlain;
|
||||
this.allowBlockPlain = allowBlockPlain;
|
||||
this.allowSingleQuoted = allowSingleQuoted;
|
||||
this.allowBlock = allowBlock;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.error;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.scanner.Constant;
|
||||
|
||||
/**
|
||||
* It's just a record and its only use is producing nice error messages. Parser
|
||||
* does not use it for any other purposes.
|
||||
*/
|
||||
public final class Mark implements Serializable {
|
||||
private String name;
|
||||
private int index;
|
||||
private int line;
|
||||
private int column;
|
||||
private int[] buffer;
|
||||
private int pointer;
|
||||
|
||||
private static int[] toCodePoints(char[] str) {
|
||||
int[] codePoints = new int[Character.codePointCount(str, 0, str.length)];
|
||||
for (int i = 0, c = 0; i < str.length; c++) {
|
||||
int cp = Character.codePointAt(str, i);
|
||||
codePoints[c] = cp;
|
||||
i += Character.charCount(cp);
|
||||
}
|
||||
return codePoints;
|
||||
}
|
||||
|
||||
public Mark(String name, int index, int line, int column, char[] str, int pointer) {
|
||||
this(name, index, line, column, toCodePoints(str), pointer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Existed in older versions but replaced with {@code char[]}-based constructor.
|
||||
* Restored in v1.22 for backwards compatibility.
|
||||
* @deprecated Since restored in v1.22. Use {@link Mark#Mark(String, int, int, int, char[], int)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public Mark(String name, int index, int line, int column, String buffer, int pointer) {
|
||||
this(name, index, line, column, buffer.toCharArray(), pointer);
|
||||
}
|
||||
|
||||
public Mark(String name, int index, int line, int column, int[] buffer, int pointer) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.index = index;
|
||||
this.line = line;
|
||||
this.column = column;
|
||||
this.buffer = buffer;
|
||||
this.pointer = pointer;
|
||||
}
|
||||
|
||||
private boolean isLineBreak(int c) {
|
||||
return Constant.NULL_OR_LINEBR.has(c);
|
||||
}
|
||||
|
||||
public String get_snippet(int indent, int max_length) {
|
||||
float half = max_length / 2 - 1;
|
||||
int start = pointer;
|
||||
String head = "";
|
||||
while ((start > 0) && !isLineBreak(buffer[start - 1])) {
|
||||
start -= 1;
|
||||
if (pointer - start > half) {
|
||||
head = " ... ";
|
||||
start += 5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
String tail = "";
|
||||
int end = pointer;
|
||||
while ((end < buffer.length) && !isLineBreak(buffer[end])) {
|
||||
end += 1;
|
||||
if (end - pointer > half) {
|
||||
tail = " ... ";
|
||||
end -= 5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (int i = 0; i < indent; i++) {
|
||||
result.append(" ");
|
||||
}
|
||||
result.append(head);
|
||||
for (int i = start; i < end; i++) {
|
||||
result.appendCodePoint(buffer[i]);
|
||||
}
|
||||
result.append(tail);
|
||||
result.append("\n");
|
||||
for (int i = 0; i < indent + pointer - start + head.length(); i++) {
|
||||
result.append(" ");
|
||||
}
|
||||
result.append("^");
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public String get_snippet() {
|
||||
return get_snippet(4, 75);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String snippet = get_snippet();
|
||||
StringBuilder builder = new StringBuilder(" in ");
|
||||
builder.append(name);
|
||||
builder.append(", line ");
|
||||
builder.append(line + 1);
|
||||
builder.append(", column ");
|
||||
builder.append(column + 1);
|
||||
builder.append(":\n");
|
||||
builder.append(snippet);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* starts with 0
|
||||
* @return line number
|
||||
*/
|
||||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
|
||||
/**
|
||||
* starts with 0
|
||||
* @return column number
|
||||
*/
|
||||
public int getColumn() {
|
||||
return column;
|
||||
}
|
||||
|
||||
/**
|
||||
* starts with 0
|
||||
* @return character number
|
||||
*/
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public int[] getBuffer() {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public int getPointer() {
|
||||
return pointer;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.error;
|
||||
|
||||
public class MarkedYAMLException extends YAMLException {
|
||||
|
||||
private static final long serialVersionUID = -9119388488683035101L;
|
||||
private String context;
|
||||
private Mark contextMark;
|
||||
private String problem;
|
||||
private Mark problemMark;
|
||||
private String note;
|
||||
|
||||
protected MarkedYAMLException(String context, Mark contextMark, String problem,
|
||||
Mark problemMark, String note) {
|
||||
this(context, contextMark, problem, problemMark, note, null);
|
||||
}
|
||||
|
||||
protected MarkedYAMLException(String context, Mark contextMark, String problem,
|
||||
Mark problemMark, String note, Throwable cause) {
|
||||
super(context + "; " + problem + "; " + problemMark, cause);
|
||||
this.context = context;
|
||||
this.contextMark = contextMark;
|
||||
this.problem = problem;
|
||||
this.problemMark = problemMark;
|
||||
this.note = note;
|
||||
}
|
||||
|
||||
protected MarkedYAMLException(String context, Mark contextMark, String problem, Mark problemMark) {
|
||||
this(context, contextMark, problem, problemMark, null, null);
|
||||
}
|
||||
|
||||
protected MarkedYAMLException(String context, Mark contextMark, String problem,
|
||||
Mark problemMark, Throwable cause) {
|
||||
this(context, contextMark, problem, problemMark, null, cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder lines = new StringBuilder();
|
||||
if (context != null) {
|
||||
lines.append(context);
|
||||
lines.append("\n");
|
||||
}
|
||||
if (contextMark != null
|
||||
&& (problem == null || problemMark == null
|
||||
|| contextMark.getName().equals(problemMark.getName())
|
||||
|| (contextMark.getLine() != problemMark.getLine()) || (contextMark
|
||||
.getColumn() != problemMark.getColumn()))) {
|
||||
lines.append(contextMark.toString());
|
||||
lines.append("\n");
|
||||
}
|
||||
if (problem != null) {
|
||||
lines.append(problem);
|
||||
lines.append("\n");
|
||||
}
|
||||
if (problemMark != null) {
|
||||
lines.append(problemMark.toString());
|
||||
lines.append("\n");
|
||||
}
|
||||
if (note != null) {
|
||||
lines.append(note);
|
||||
lines.append("\n");
|
||||
}
|
||||
return lines.toString();
|
||||
}
|
||||
|
||||
public String getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public Mark getContextMark() {
|
||||
return contextMark;
|
||||
}
|
||||
|
||||
public String getProblem() {
|
||||
return problem;
|
||||
}
|
||||
|
||||
public Mark getProblemMark() {
|
||||
return problemMark;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.error;
|
||||
|
||||
public class YAMLException extends RuntimeException {
|
||||
private static final long serialVersionUID = -4738336175050337570L;
|
||||
|
||||
public YAMLException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public YAMLException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public YAMLException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.events;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
/**
|
||||
* Marks the inclusion of a previously anchored node.
|
||||
*/
|
||||
public final class AliasEvent extends NodeEvent {
|
||||
public AliasEvent(String anchor, Mark startMark, Mark endMark) {
|
||||
super(anchor, startMark, endMark);
|
||||
if(anchor == null) throw new NullPointerException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is(Event.ID id) {
|
||||
return ID.Alias == id;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.events;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
/**
|
||||
* Base class for the end events of the collection nodes.
|
||||
*/
|
||||
public abstract class CollectionEndEvent extends Event {
|
||||
|
||||
public CollectionEndEvent(Mark startMark, Mark endMark) {
|
||||
super(startMark, endMark);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.events;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.DumperOptions;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
/**
|
||||
* Base class for the start events of the collection nodes.
|
||||
*/
|
||||
public abstract class CollectionStartEvent extends NodeEvent {
|
||||
private final String tag;
|
||||
// The implicit flag of a collection start event indicates if the tag may be
|
||||
// omitted when the collection is emitted
|
||||
private final boolean implicit;
|
||||
// flag indicates if a collection is block or flow
|
||||
private final DumperOptions.FlowStyle flowStyle;
|
||||
|
||||
public CollectionStartEvent(String anchor, String tag, boolean implicit, Mark startMark,
|
||||
Mark endMark, DumperOptions.FlowStyle flowStyle) {
|
||||
super(anchor, startMark, endMark);
|
||||
this.tag = tag;
|
||||
this.implicit = implicit;
|
||||
if(flowStyle == null) throw new NullPointerException("Flow style must be provided.");
|
||||
this.flowStyle = flowStyle;
|
||||
}
|
||||
|
||||
/*
|
||||
* Existed in older versions but replaced with {@link DumperOptions.FlowStyle}-based constructor.
|
||||
* Restored in v1.22 for backwards compatibility.
|
||||
* @deprecated Since restored in v1.22. Use {@link CollectionStartEvent#CollectionStartEvent(String, String, boolean, Mark, Mark, io.jenkins.plugins.casc.snakeyaml.DumperOptions.FlowStyle) }.
|
||||
*/
|
||||
@Deprecated
|
||||
public CollectionStartEvent(String anchor, String tag, boolean implicit, Mark startMark,
|
||||
Mark endMark, Boolean flowStyle) {
|
||||
this(anchor, tag, implicit, startMark, endMark, DumperOptions.FlowStyle.fromBoolean(flowStyle));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag of this collection.
|
||||
*
|
||||
* @return The tag of this collection, or <code>null</code> if no explicit
|
||||
* tag is available.
|
||||
*/
|
||||
public String getTag() {
|
||||
return this.tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>true</code> if the tag can be omitted while this collection is
|
||||
* emitted.
|
||||
*
|
||||
* @return True if the tag can be omitted while this collection is emitted.
|
||||
*/
|
||||
public boolean getImplicit() {
|
||||
return this.implicit;
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>true</code> if this collection is in flow style, <code>false</code>
|
||||
* for block style.
|
||||
*
|
||||
* @return If this collection is in flow style.
|
||||
*/
|
||||
public DumperOptions.FlowStyle getFlowStyle() {
|
||||
return this.flowStyle;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getArguments() {
|
||||
return super.getArguments() + ", tag=" + tag + ", implicit=" + implicit;
|
||||
}
|
||||
|
||||
public boolean isFlow() {
|
||||
return DumperOptions.FlowStyle.FLOW == flowStyle;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.events;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
/**
|
||||
* Marks the end of a document.
|
||||
* <p>
|
||||
* This event follows the document's content.
|
||||
* </p>
|
||||
*/
|
||||
public final class DocumentEndEvent extends Event {
|
||||
private final boolean explicit;
|
||||
|
||||
public DocumentEndEvent(Mark startMark, Mark endMark, boolean explicit) {
|
||||
super(startMark, endMark);
|
||||
this.explicit = explicit;
|
||||
}
|
||||
|
||||
public boolean getExplicit() {
|
||||
return explicit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is(Event.ID id) {
|
||||
return ID.DocumentEnd == id;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.events;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.DumperOptions.Version;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
/**
|
||||
* Marks the beginning of a document.
|
||||
* <p>
|
||||
* This event followed by the document's content and a {@link DocumentEndEvent}.
|
||||
* </p>
|
||||
*/
|
||||
public final class DocumentStartEvent extends Event {
|
||||
private final boolean explicit;
|
||||
private final Version version;
|
||||
private final Map<String, String> tags;
|
||||
|
||||
public DocumentStartEvent(Mark startMark, Mark endMark, boolean explicit, Version version,
|
||||
Map<String, String> tags) {
|
||||
super(startMark, endMark);
|
||||
this.explicit = explicit;
|
||||
this.version = version;
|
||||
this.tags = tags;
|
||||
}
|
||||
|
||||
public boolean getExplicit() {
|
||||
return explicit;
|
||||
}
|
||||
|
||||
/**
|
||||
* YAML version the document conforms to.
|
||||
*
|
||||
* @return <code>null</code>if the document has no explicit
|
||||
* <code>%YAML</code> directive. Otherwise an array with two
|
||||
* components, the major and minor part of the version (in this
|
||||
* order).
|
||||
*/
|
||||
public Version getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag shorthands as defined by the <code>%TAG</code> directive.
|
||||
*
|
||||
* @return Mapping of 'handles' to 'prefixes' (the handles include the '!'
|
||||
* characters).
|
||||
*/
|
||||
public Map<String, String> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is(Event.ID id) {
|
||||
return ID.DocumentStart == id;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.events;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
/**
|
||||
* Basic unit of output from a {@link io.jenkins.plugins.casc.snakeyaml.parser.Parser} or input
|
||||
* of a {@link io.jenkins.plugins.casc.snakeyaml.emitter.Emitter}.
|
||||
*/
|
||||
public abstract class Event {
|
||||
public enum ID {
|
||||
Alias, DocumentEnd, DocumentStart, MappingEnd, MappingStart, Scalar, SequenceEnd, SequenceStart, StreamEnd, StreamStart
|
||||
}
|
||||
|
||||
private final Mark startMark;
|
||||
private final Mark endMark;
|
||||
|
||||
public Event(Mark startMark, Mark endMark) {
|
||||
this.startMark = startMark;
|
||||
this.endMark = endMark;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "<" + this.getClass().getName() + "(" + getArguments() + ")>";
|
||||
}
|
||||
|
||||
public Mark getStartMark() {
|
||||
return startMark;
|
||||
}
|
||||
|
||||
public Mark getEndMark() {
|
||||
return endMark;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate human readable representation of the Event
|
||||
* @see "__repr__ for Event in PyYAML"
|
||||
* @return representation fore humans
|
||||
*/
|
||||
protected String getArguments() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public abstract boolean is(Event.ID id);
|
||||
|
||||
/*
|
||||
* for tests only
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof Event) {
|
||||
return toString().equals(obj.toString());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* for tests only
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return toString().hashCode();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.events;
|
||||
|
||||
/**
|
||||
* The implicit flag of a scalar event is a pair of boolean values that indicate
|
||||
* if the tag may be omitted when the scalar is emitted in a plain and non-plain
|
||||
* style correspondingly.
|
||||
*
|
||||
* @see <a href="http://pyyaml.org/wiki/PyYAMLDocumentation#Events">Events</a>
|
||||
*/
|
||||
public class ImplicitTuple {
|
||||
private final boolean plain;
|
||||
private final boolean nonPlain;
|
||||
|
||||
public ImplicitTuple(boolean plain, boolean nonplain) {
|
||||
this.plain = plain;
|
||||
this.nonPlain = nonplain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true when tag may be omitted when the scalar is emitted in a
|
||||
* plain style.
|
||||
*/
|
||||
public boolean canOmitTagInPlainScalar() {
|
||||
return plain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true when tag may be omitted when the scalar is emitted in a
|
||||
* non-plain style.
|
||||
*/
|
||||
public boolean canOmitTagInNonPlainScalar() {
|
||||
return nonPlain;
|
||||
}
|
||||
|
||||
public boolean bothFalse() {
|
||||
return !plain && !nonPlain;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "implicit=[" + plain + ", " + nonPlain + "]";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.events;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
/**
|
||||
* Marks the end of a mapping node.
|
||||
*
|
||||
* @see MappingStartEvent
|
||||
*/
|
||||
public final class MappingEndEvent extends CollectionEndEvent {
|
||||
|
||||
public MappingEndEvent(Mark startMark, Mark endMark) {
|
||||
super(startMark, endMark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is(Event.ID id) {
|
||||
return ID.MappingEnd == id;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.events;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.DumperOptions;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
/**
|
||||
* Marks the beginning of a mapping node.
|
||||
* <p>
|
||||
* This event is followed by a number of key value pairs. <br>
|
||||
* The pairs are not in any particular order. However, the value always directly
|
||||
* follows the corresponding key. <br>
|
||||
* After the key value pairs follows a {@link MappingEndEvent}.
|
||||
* </p>
|
||||
* <p>
|
||||
* There must be an even number of node events between the start and end event.
|
||||
* </p>
|
||||
*
|
||||
* @see MappingEndEvent
|
||||
*/
|
||||
public final class MappingStartEvent extends CollectionStartEvent {
|
||||
public MappingStartEvent(String anchor, String tag, boolean implicit, Mark startMark,
|
||||
Mark endMark, DumperOptions.FlowStyle flowStyle) {
|
||||
super(anchor, tag, implicit, startMark, endMark, flowStyle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Existed in older versions but replaced with {@link DumperOptions.FlowStyle}-based constructor.
|
||||
* Restored in v1.22 for backwards compatibility.
|
||||
* @deprecated Since restored in v1.22. Use {@link MappingStartEvent#CollectionStartEvent(String, String, boolean, Mark, Mark, io.jenkins.plugins.casc.snakeyaml.DumperOptions.FlowStyle) }.
|
||||
*/
|
||||
@Deprecated
|
||||
public MappingStartEvent(String anchor, String tag, boolean implicit, Mark startMark,
|
||||
Mark endMark, Boolean flowStyle) {
|
||||
this(anchor, tag, implicit, startMark, endMark, DumperOptions.FlowStyle.fromBoolean(flowStyle));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is(Event.ID id) {
|
||||
return ID.MappingStart == id;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.events;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
/**
|
||||
* Base class for all events that mark the beginning of a node.
|
||||
*/
|
||||
public abstract class NodeEvent extends Event {
|
||||
|
||||
private final String anchor;
|
||||
|
||||
public NodeEvent(String anchor, Mark startMark, Mark endMark) {
|
||||
super(startMark, endMark);
|
||||
this.anchor = anchor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Node anchor by which this node might later be referenced by a
|
||||
* {@link AliasEvent}.
|
||||
* <p>
|
||||
* Note that {@link AliasEvent}s are by it self <code>NodeEvent</code>s and
|
||||
* use this property to indicate the referenced anchor.
|
||||
*
|
||||
* @return Anchor of this node or <code>null</code> if no anchor is defined.
|
||||
*/
|
||||
public String getAnchor() {
|
||||
return this.anchor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getArguments() {
|
||||
return "anchor=" + anchor;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.events;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.DumperOptions;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
/**
|
||||
* Marks a scalar value.
|
||||
*/
|
||||
public final class ScalarEvent extends NodeEvent {
|
||||
private final String tag;
|
||||
// style flag of a scalar event indicates the style of the scalar. Possible
|
||||
// values are None, '', '\'', '"', '|', '>'
|
||||
private final DumperOptions.ScalarStyle style;
|
||||
private final String value;
|
||||
// The implicit flag of a scalar event is a pair of boolean values that
|
||||
// indicate if the tag may be omitted when the scalar is emitted in a plain
|
||||
// and non-plain style correspondingly.
|
||||
private final ImplicitTuple implicit;
|
||||
|
||||
public ScalarEvent(String anchor, String tag, ImplicitTuple implicit, String value,
|
||||
Mark startMark, Mark endMark, DumperOptions.ScalarStyle style) {
|
||||
super(anchor, startMark, endMark);
|
||||
this.tag = tag;
|
||||
this.implicit = implicit;
|
||||
if (value == null) throw new NullPointerException("Value must be provided.");
|
||||
this.value = value;
|
||||
if (style == null) throw new NullPointerException("Style must be provided.");
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
/*
|
||||
* Existed in older versions but replaced with {@link DumperOptions.ScalarStyle}-based constructor.
|
||||
* Restored in v1.22 for backwards compatibility.
|
||||
* @deprecated Since restored in v1.22. Use {@link ScalarEvent#ScalarEvent(String, String, ImplicitTuple, String, Mark, Mark, io.jenkins.plugins.casc.snakeyaml.DumperOptions.ScalarStyle) }.
|
||||
*/
|
||||
@Deprecated
|
||||
public ScalarEvent(String anchor, String tag, ImplicitTuple implicit, String value,
|
||||
Mark startMark, Mark endMark, Character style) {
|
||||
this(anchor, tag, implicit, value, startMark, endMark, DumperOptions.ScalarStyle.createStyle(style));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag of this scalar.
|
||||
*
|
||||
* @return The tag of this scalar, or <code>null</code> if no explicit tag
|
||||
* is available.
|
||||
*/
|
||||
public String getTag() {
|
||||
return this.tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Style of the scalar.
|
||||
* <dl>
|
||||
* <dt>null</dt>
|
||||
* <dd>Flow Style - Plain</dd>
|
||||
* <dt>'\''</dt>
|
||||
* <dd>Flow Style - Single-Quoted</dd>
|
||||
* <dt>'"'</dt>
|
||||
* <dd>Flow Style - Double-Quoted</dd>
|
||||
* <dt>'|'</dt>
|
||||
* <dd>Block Style - Literal</dd>
|
||||
* <dt>'>'</dt>
|
||||
* <dd>Block Style - Folded</dd>
|
||||
* </dl>
|
||||
*
|
||||
* @see <a href="http://yaml.org/spec/1.1/#id864487">Kind/Style
|
||||
* Combinations</a>
|
||||
* @return Style of the scalar.
|
||||
*/
|
||||
public DumperOptions.ScalarStyle getScalarStyle() {
|
||||
return this.style;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use getScalarStyle() instead
|
||||
* @return char which is a value behind ScalarStyle
|
||||
*/
|
||||
@Deprecated
|
||||
public Character getStyle() {
|
||||
return this.style.getChar();
|
||||
}
|
||||
|
||||
/**
|
||||
* String representation of the value.
|
||||
* <p>
|
||||
* Without quotes and escaping.
|
||||
* </p>
|
||||
*
|
||||
* @return Value as Unicode string.
|
||||
*/
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public ImplicitTuple getImplicit() {
|
||||
return this.implicit;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getArguments() {
|
||||
return super.getArguments() + ", tag=" + tag + ", " + implicit + ", value=" + value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is(Event.ID id) {
|
||||
return ID.Scalar == id;
|
||||
}
|
||||
|
||||
public boolean isPlain() {
|
||||
return style == DumperOptions.ScalarStyle.PLAIN;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.events;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
/**
|
||||
* Marks the end of a sequence.
|
||||
*
|
||||
* @see SequenceStartEvent
|
||||
*/
|
||||
public final class SequenceEndEvent extends CollectionEndEvent {
|
||||
|
||||
public SequenceEndEvent(Mark startMark, Mark endMark) {
|
||||
super(startMark, endMark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is(Event.ID id) {
|
||||
return ID.SequenceEnd == id;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.events;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.DumperOptions;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
/**
|
||||
* Marks the beginning of a sequence node.
|
||||
* <p>
|
||||
* This event is followed by the elements contained in the sequence, and a
|
||||
* {@link SequenceEndEvent}.
|
||||
* </p>
|
||||
*
|
||||
* @see SequenceEndEvent
|
||||
*/
|
||||
public final class SequenceStartEvent extends CollectionStartEvent {
|
||||
public SequenceStartEvent(String anchor, String tag, boolean implicit, Mark startMark,
|
||||
Mark endMark, DumperOptions.FlowStyle flowStyle) {
|
||||
super(anchor, tag, implicit, startMark, endMark, flowStyle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Existed in older versions but replaced with {@link DumperOptions.SequenceStyle}-based constructor.
|
||||
* Restored in v1.22 for backwards compatibility.
|
||||
* @deprecated Since restored in v1.22. Use {@link SequenceStartEvent#SequenceStartEvent(String, String, boolean, Mark, Mark, io.jenkins.plugins.casc.snakeyaml.DumperOptions.FlowStyle) }.
|
||||
*/
|
||||
@Deprecated
|
||||
public SequenceStartEvent(String anchor, String tag, boolean implicit, Mark startMark,
|
||||
Mark endMark, Boolean flowStyle) {
|
||||
this(anchor, tag, implicit, startMark, endMark, DumperOptions.FlowStyle.fromBoolean(flowStyle));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is(Event.ID id) {
|
||||
return ID.SequenceStart == id;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.events;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
/**
|
||||
* Marks the end of a stream that might have contained multiple documents.
|
||||
* <p>
|
||||
* This event is the last event that a parser emits. Together with
|
||||
* {@link StreamStartEvent} (which is the first event a parser emits) they mark
|
||||
* the beginning and the end of a stream of documents.
|
||||
* </p>
|
||||
* <p>
|
||||
* See {@link Event} for an exemplary output.
|
||||
* </p>
|
||||
*/
|
||||
public final class StreamEndEvent extends Event {
|
||||
public StreamEndEvent(Mark startMark, Mark endMark) {
|
||||
super(startMark, endMark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is(Event.ID id) {
|
||||
return ID.StreamEnd == id;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.events;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
/**
|
||||
* Marks the start of a stream that might contain multiple documents.
|
||||
* <p>
|
||||
* This event is the first event that a parser emits. Together with
|
||||
* {@link StreamEndEvent} (which is the last event a parser emits) they mark the
|
||||
* beginning and the end of a stream of documents.
|
||||
* </p>
|
||||
* <p>
|
||||
* See {@link Event} for an exemplary output.
|
||||
* </p>
|
||||
*/
|
||||
public final class StreamStartEvent extends Event {
|
||||
|
||||
public StreamStartEvent(Mark startMark, Mark endMark) {
|
||||
super(startMark, endMark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is(Event.ID id) {
|
||||
return ID.StreamStart == id;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,235 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.extensions.compactnotation;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.constructor.Construct;
|
||||
import io.jenkins.plugins.casc.snakeyaml.constructor.Constructor;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.YAMLException;
|
||||
import io.jenkins.plugins.casc.snakeyaml.introspector.Property;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.MappingNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Node;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.NodeTuple;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.ScalarNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.SequenceNode;
|
||||
|
||||
/**
|
||||
* Construct a custom Java instance out of a compact object notation format.
|
||||
*/
|
||||
public class CompactConstructor extends Constructor {
|
||||
private static final Pattern GUESS_COMPACT = Pattern
|
||||
.compile("\\p{Alpha}.*\\s*\\((?:,?\\s*(?:(?:\\w*)|(?:\\p{Alpha}\\w*\\s*=.+))\\s*)+\\)");
|
||||
private static final Pattern FIRST_PATTERN = Pattern.compile("(\\p{Alpha}.*)(\\s*)\\((.*?)\\)");
|
||||
private static final Pattern PROPERTY_NAME_PATTERN = Pattern
|
||||
.compile("\\s*(\\p{Alpha}\\w*)\\s*=(.+)");
|
||||
private Construct compactConstruct;
|
||||
|
||||
protected Object constructCompactFormat(ScalarNode node, CompactData data) {
|
||||
try {
|
||||
Object obj = createInstance(node, data);
|
||||
Map<String, Object> properties = new HashMap<String, Object>(data.getProperties());
|
||||
setProperties(obj, properties);
|
||||
return obj;
|
||||
} catch (Exception e) {
|
||||
throw new YAMLException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected Object createInstance(ScalarNode node, CompactData data) throws Exception {
|
||||
Class<?> clazz = getClassForName(data.getPrefix());
|
||||
Class<?>[] args = new Class[data.getArguments().size()];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
// assume all the arguments are Strings
|
||||
args[i] = String.class;
|
||||
}
|
||||
java.lang.reflect.Constructor<?> c = clazz.getDeclaredConstructor(args);
|
||||
c.setAccessible(true);
|
||||
return c.newInstance(data.getArguments().toArray());
|
||||
|
||||
}
|
||||
|
||||
protected void setProperties(Object bean, Map<String, Object> data) throws Exception {
|
||||
if (data == null) {
|
||||
throw new NullPointerException("Data for Compact Object Notation cannot be null.");
|
||||
}
|
||||
for (Map.Entry<String, Object> entry : data.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
Property property = getPropertyUtils().getProperty(bean.getClass(), key);
|
||||
try {
|
||||
property.set(bean, entry.getValue());
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new YAMLException("Cannot set property='" + key + "' with value='"
|
||||
+ data.get(key) + "' (" + data.get(key).getClass() + ") in " + bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public CompactData getCompactData(String scalar) {
|
||||
if (!scalar.endsWith(")")) {
|
||||
return null;
|
||||
}
|
||||
if (scalar.indexOf('(') < 0) {
|
||||
return null;
|
||||
}
|
||||
Matcher m = FIRST_PATTERN.matcher(scalar);
|
||||
if (m.matches()) {
|
||||
String tag = m.group(1).trim();
|
||||
String content = m.group(3);
|
||||
CompactData data = new CompactData(tag);
|
||||
if (content.length() == 0)
|
||||
return data;
|
||||
String[] names = content.split("\\s*,\\s*");
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
String section = names[i];
|
||||
if (section.indexOf('=') < 0) {
|
||||
data.getArguments().add(section);
|
||||
} else {
|
||||
Matcher sm = PROPERTY_NAME_PATTERN.matcher(section);
|
||||
if (sm.matches()) {
|
||||
String name = sm.group(1);
|
||||
String value = sm.group(2).trim();
|
||||
data.getProperties().put(name, value);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Construct getCompactConstruct() {
|
||||
if (compactConstruct == null) {
|
||||
compactConstruct = createCompactConstruct();
|
||||
}
|
||||
return compactConstruct;
|
||||
}
|
||||
|
||||
protected Construct createCompactConstruct() {
|
||||
return new ConstructCompactObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Construct getConstructor(Node node) {
|
||||
if (node instanceof MappingNode) {
|
||||
MappingNode mnode = (MappingNode) node;
|
||||
List<NodeTuple> list = mnode.getValue();
|
||||
if (list.size() == 1) {
|
||||
NodeTuple tuple = list.get(0);
|
||||
Node key = tuple.getKeyNode();
|
||||
if (key instanceof ScalarNode) {
|
||||
ScalarNode scalar = (ScalarNode) key;
|
||||
if (GUESS_COMPACT.matcher(scalar.getValue()).matches()) {
|
||||
return getCompactConstruct();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (node instanceof ScalarNode) {
|
||||
ScalarNode scalar = (ScalarNode) node;
|
||||
if (GUESS_COMPACT.matcher(scalar.getValue()).matches()) {
|
||||
return getCompactConstruct();
|
||||
}
|
||||
}
|
||||
return super.getConstructor(node);
|
||||
}
|
||||
|
||||
public class ConstructCompactObject extends ConstructMapping {
|
||||
|
||||
@Override
|
||||
public void construct2ndStep(Node node, Object object) {
|
||||
// Compact Object Notation may contain only one entry
|
||||
MappingNode mnode = (MappingNode) node;
|
||||
NodeTuple nodeTuple = mnode.getValue().iterator().next();
|
||||
|
||||
Node valueNode = nodeTuple.getValueNode();
|
||||
|
||||
if (valueNode instanceof MappingNode) {
|
||||
valueNode.setType(object.getClass());
|
||||
constructJavaBean2ndStep((MappingNode) valueNode, object);
|
||||
} else {
|
||||
// value is a list
|
||||
applySequence(object, constructSequence((SequenceNode) valueNode));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* MappingNode and ScalarNode end up here only they assumed to be a
|
||||
* compact object's representation (@see getConstructor(Node) above)
|
||||
*/
|
||||
public Object construct(Node node) {
|
||||
ScalarNode tmpNode;
|
||||
if (node instanceof MappingNode) {
|
||||
// Compact Object Notation may contain only one entry
|
||||
MappingNode mnode = (MappingNode) node;
|
||||
NodeTuple nodeTuple = mnode.getValue().iterator().next();
|
||||
node.setTwoStepsConstruction(true);
|
||||
tmpNode = (ScalarNode) nodeTuple.getKeyNode();
|
||||
// return constructScalar((ScalarNode) keyNode);
|
||||
} else {
|
||||
tmpNode = (ScalarNode) node;
|
||||
}
|
||||
|
||||
CompactData data = getCompactData(tmpNode.getValue());
|
||||
if (data == null) { // TODO: Should we throw an exception here ?
|
||||
return constructScalar(tmpNode);
|
||||
}
|
||||
return constructCompactFormat(tmpNode, data);
|
||||
}
|
||||
}
|
||||
|
||||
protected void applySequence(Object bean, List<?> value) {
|
||||
try {
|
||||
Property property = getPropertyUtils().getProperty(bean.getClass(),
|
||||
getSequencePropertyName(bean.getClass()));
|
||||
property.set(bean, value);
|
||||
} catch (Exception e) {
|
||||
throw new YAMLException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide the name of the property which is used when the entries form a
|
||||
* sequence. The property must be a List.
|
||||
* @param bean the class to provide exactly one List property
|
||||
* @return name of the List property
|
||||
*/
|
||||
protected String getSequencePropertyName(Class<?> bean) {
|
||||
Set<Property> properties = getPropertyUtils().getProperties(bean);
|
||||
for (Iterator<Property> iterator = properties.iterator(); iterator.hasNext();) {
|
||||
Property property = iterator.next();
|
||||
if (!List.class.isAssignableFrom(property.getType())) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
if (properties.size() == 0) {
|
||||
throw new YAMLException("No list property found in " + bean);
|
||||
} else if (properties.size() > 1) {
|
||||
throw new YAMLException(
|
||||
"Many list properties found in "
|
||||
+ bean
|
||||
+ "; Please override getSequencePropertyName() to specify which property to use.");
|
||||
}
|
||||
return properties.iterator().next().getName();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.extensions.compactnotation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CompactData {
|
||||
private String prefix;
|
||||
private List<String> arguments = new ArrayList<String>();
|
||||
private Map<String, String> properties = new HashMap<String, String>();
|
||||
|
||||
public CompactData(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public Map<String, String> getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public List<String> getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CompactData: " + prefix + " " + properties;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.extensions.compactnotation;
|
||||
|
||||
public class PackageCompactConstructor extends CompactConstructor {
|
||||
private String packageName;
|
||||
|
||||
public PackageCompactConstructor(String packageName) {
|
||||
this.packageName = packageName;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getClassForName(String name) throws ClassNotFoundException {
|
||||
if (name.indexOf('.') < 0) {
|
||||
try {
|
||||
Class<?> clazz = Class.forName(packageName + "." + name);
|
||||
return clazz;
|
||||
} catch (ClassNotFoundException e) {
|
||||
// use super implementation
|
||||
}
|
||||
}
|
||||
return super.getClassForName(name);
|
||||
}
|
||||
}
|
||||
305
snakeyaml/src/main/java/io/jenkins/plugins/casc/snakeyaml/external/biz/base64Coder/Base64Coder.java
vendored
Normal file
305
snakeyaml/src/main/java/io/jenkins/plugins/casc/snakeyaml/external/biz/base64Coder/Base64Coder.java
vendored
Normal file
|
|
@ -0,0 +1,305 @@
|
|||
// Copyright 2003-2010 Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland
|
||||
// www.source-code.biz, www.inventec.ch/chdh
|
||||
//
|
||||
// This module is multi-licensed and may be used under the terms
|
||||
// of any of the following licenses:
|
||||
//
|
||||
// EPL, Eclipse Public License, V1.0 or later, http://www.eclipse.org/legal
|
||||
// LGPL, GNU Lesser General Public License, V2.1 or later, http://www.gnu.org/licenses/lgpl.html
|
||||
// GPL, GNU General Public License, V2 or later, http://www.gnu.org/licenses/gpl.html
|
||||
// AL, Apache License, V2.0 or later, http://www.apache.org/licenses
|
||||
// BSD, BSD License, http://www.opensource.org/licenses/bsd-license.php
|
||||
//
|
||||
// Please contact the author if you need another license.
|
||||
// This module is provided "as is", without warranties of any kind.
|
||||
|
||||
package io.jenkins.plugins.casc.snakeyaml.external.biz.base64Coder;
|
||||
|
||||
/**
|
||||
* A Base64 encoder/decoder.
|
||||
*
|
||||
* <p>
|
||||
* This class is used to encode and decode data in Base64 format as described in
|
||||
* RFC 1521.
|
||||
*
|
||||
* <p>
|
||||
* Project home page: <a
|
||||
* href="http://www.source-code.biz/base64coder/java/">www.
|
||||
* source-code.biz/base64coder/java</a><br>
|
||||
* Author: Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland<br>
|
||||
* Multi-licensed: EPL / LGPL / GPL / AL / BSD.
|
||||
*/
|
||||
public class Base64Coder {
|
||||
|
||||
// The line separator string of the operating system.
|
||||
private static final String systemLineSeparator = System.getProperty("line.separator");
|
||||
|
||||
// Mapping table from 6-bit nibbles to Base64 characters.
|
||||
private static char[] map1 = new char[64];
|
||||
static {
|
||||
int i = 0;
|
||||
for (char c = 'A'; c <= 'Z'; c++)
|
||||
map1[i++] = c;
|
||||
for (char c = 'a'; c <= 'z'; c++)
|
||||
map1[i++] = c;
|
||||
for (char c = '0'; c <= '9'; c++)
|
||||
map1[i++] = c;
|
||||
map1[i++] = '+';
|
||||
map1[i++] = '/';
|
||||
}
|
||||
|
||||
// Mapping table from Base64 characters to 6-bit nibbles.
|
||||
private static byte[] map2 = new byte[128];
|
||||
static {
|
||||
for (int i = 0; i < map2.length; i++)
|
||||
map2[i] = -1;
|
||||
for (int i = 0; i < 64; i++)
|
||||
map2[map1[i]] = (byte) i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a string into Base64 format. No blanks or line breaks are
|
||||
* inserted.
|
||||
*
|
||||
* @param s
|
||||
* A String to be encoded.
|
||||
* @return A String containing the Base64 encoded data.
|
||||
*/
|
||||
public static String encodeString(String s) {
|
||||
return new String(encode(s.getBytes()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a byte array into Base 64 format and breaks the output into lines
|
||||
* of 76 characters. This method is compatible with
|
||||
* <code>sun.misc.BASE64Encoder.encodeBuffer(byte[])</code>.
|
||||
*
|
||||
* @param in
|
||||
* An array containing the data bytes to be encoded.
|
||||
* @return A String containing the Base64 encoded data, broken into lines.
|
||||
*/
|
||||
public static String encodeLines(byte[] in) {
|
||||
return encodeLines(in, 0, in.length, 76, systemLineSeparator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a byte array into Base 64 format and breaks the output into
|
||||
* lines.
|
||||
*
|
||||
* @param in
|
||||
* An array containing the data bytes to be encoded.
|
||||
* @param iOff
|
||||
* Offset of the first byte in <code>in</code> to be processed.
|
||||
* @param iLen
|
||||
* Number of bytes to be processed in <code>in</code>, starting
|
||||
* at <code>iOff</code>.
|
||||
* @param lineLen
|
||||
* Line length for the output data. Should be a multiple of 4.
|
||||
* @param lineSeparator
|
||||
* The line separator to be used to separate the output lines.
|
||||
* @return A String containing the Base64 encoded data, broken into lines.
|
||||
*/
|
||||
public static String encodeLines(byte[] in, int iOff, int iLen, int lineLen,
|
||||
String lineSeparator) {
|
||||
int blockLen = (lineLen * 3) / 4;
|
||||
if (blockLen <= 0)
|
||||
throw new IllegalArgumentException();
|
||||
int lines = (iLen + blockLen - 1) / blockLen;
|
||||
int bufLen = ((iLen + 2) / 3) * 4 + lines * lineSeparator.length();
|
||||
StringBuilder buf = new StringBuilder(bufLen);
|
||||
int ip = 0;
|
||||
while (ip < iLen) {
|
||||
int l = Math.min(iLen - ip, blockLen);
|
||||
buf.append(encode(in, iOff + ip, l));
|
||||
buf.append(lineSeparator);
|
||||
ip += l;
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a byte array into Base64 format. No blanks or line breaks are
|
||||
* inserted in the output.
|
||||
*
|
||||
* @param in
|
||||
* An array containing the data bytes to be encoded.
|
||||
* @return A character array containing the Base64 encoded data.
|
||||
*/
|
||||
public static char[] encode(byte[] in) {
|
||||
return encode(in, 0, in.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a byte array into Base64 format. No blanks or line breaks are
|
||||
* inserted in the output.
|
||||
*
|
||||
* @param in
|
||||
* An array containing the data bytes to be encoded.
|
||||
* @param iLen
|
||||
* Number of bytes to process in <code>in</code>.
|
||||
* @return A character array containing the Base64 encoded data.
|
||||
*/
|
||||
public static char[] encode(byte[] in, int iLen) {
|
||||
return encode(in, 0, iLen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a byte array into Base64 format. No blanks or line breaks are
|
||||
* inserted in the output.
|
||||
*
|
||||
* @param in
|
||||
* An array containing the data bytes to be encoded.
|
||||
* @param iOff
|
||||
* Offset of the first byte in <code>in</code> to be processed.
|
||||
* @param iLen
|
||||
* Number of bytes to process in <code>in</code>, starting at
|
||||
* <code>iOff</code>.
|
||||
* @return A character array containing the Base64 encoded data.
|
||||
*/
|
||||
public static char[] encode(byte[] in, int iOff, int iLen) {
|
||||
int oDataLen = (iLen * 4 + 2) / 3; // output length without padding
|
||||
int oLen = ((iLen + 2) / 3) * 4; // output length including padding
|
||||
char[] out = new char[oLen];
|
||||
int ip = iOff;
|
||||
int iEnd = iOff + iLen;
|
||||
int op = 0;
|
||||
while (ip < iEnd) {
|
||||
int i0 = in[ip++] & 0xff;
|
||||
int i1 = ip < iEnd ? in[ip++] & 0xff : 0;
|
||||
int i2 = ip < iEnd ? in[ip++] & 0xff : 0;
|
||||
int o0 = i0 >>> 2;
|
||||
int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
|
||||
int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
|
||||
int o3 = i2 & 0x3F;
|
||||
out[op++] = map1[o0];
|
||||
out[op++] = map1[o1];
|
||||
out[op] = op < oDataLen ? map1[o2] : '=';
|
||||
op++;
|
||||
out[op] = op < oDataLen ? map1[o3] : '=';
|
||||
op++;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a string from Base64 format. No blanks or line breaks are allowed
|
||||
* within the Base64 encoded input data.
|
||||
*
|
||||
* @param s
|
||||
* A Base64 String to be decoded.
|
||||
* @return A String containing the decoded data.
|
||||
* @throws IllegalArgumentException
|
||||
* If the input is not valid Base64 encoded data.
|
||||
*/
|
||||
public static String decodeString(String s) {
|
||||
return new String(decode(s));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a byte array from Base64 format and ignores line separators, tabs
|
||||
* and blanks. CR, LF, Tab and Space characters are ignored in the input
|
||||
* data. This method is compatible with
|
||||
* <code>sun.misc.BASE64Decoder.decodeBuffer(String)</code>.
|
||||
*
|
||||
* @param s
|
||||
* A Base64 String to be decoded.
|
||||
* @return An array containing the decoded data bytes.
|
||||
* @throws IllegalArgumentException
|
||||
* If the input is not valid Base64 encoded data.
|
||||
*/
|
||||
public static byte[] decodeLines(String s) {
|
||||
char[] buf = new char[s.length()];
|
||||
int p = 0;
|
||||
for (int ip = 0; ip < s.length(); ip++) {
|
||||
char c = s.charAt(ip);
|
||||
if (c != ' ' && c != '\r' && c != '\n' && c != '\t')
|
||||
buf[p++] = c;
|
||||
}
|
||||
return decode(buf, 0, p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a byte array from Base64 format. No blanks or line breaks are
|
||||
* allowed within the Base64 encoded input data.
|
||||
*
|
||||
* @param s
|
||||
* A Base64 String to be decoded.
|
||||
* @return An array containing the decoded data bytes.
|
||||
* @throws IllegalArgumentException
|
||||
* If the input is not valid Base64 encoded data.
|
||||
*/
|
||||
public static byte[] decode(String s) {
|
||||
return decode(s.toCharArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a byte array from Base64 format. No blanks or line breaks are
|
||||
* allowed within the Base64 encoded input data.
|
||||
*
|
||||
* @param in
|
||||
* A character array containing the Base64 encoded data.
|
||||
* @return An array containing the decoded data bytes.
|
||||
* @throws IllegalArgumentException
|
||||
* If the input is not valid Base64 encoded data.
|
||||
*/
|
||||
public static byte[] decode(char[] in) {
|
||||
return decode(in, 0, in.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a byte array from Base64 format. No blanks or line breaks are
|
||||
* allowed within the Base64 encoded input data.
|
||||
*
|
||||
* @param in
|
||||
* A character array containing the Base64 encoded data.
|
||||
* @param iOff
|
||||
* Offset of the first character in <code>in</code> to be
|
||||
* processed.
|
||||
* @param iLen
|
||||
* Number of characters to process in <code>in</code>, starting
|
||||
* at <code>iOff</code>.
|
||||
* @return An array containing the decoded data bytes.
|
||||
* @throws IllegalArgumentException
|
||||
* If the input is not valid Base64 encoded data.
|
||||
*/
|
||||
public static byte[] decode(char[] in, int iOff, int iLen) {
|
||||
if (iLen % 4 != 0)
|
||||
throw new IllegalArgumentException(
|
||||
"Length of Base64 encoded input string is not a multiple of 4.");
|
||||
while (iLen > 0 && in[iOff + iLen - 1] == '=')
|
||||
iLen--;
|
||||
int oLen = (iLen * 3) / 4;
|
||||
byte[] out = new byte[oLen];
|
||||
int ip = iOff;
|
||||
int iEnd = iOff + iLen;
|
||||
int op = 0;
|
||||
while (ip < iEnd) {
|
||||
int i0 = in[ip++];
|
||||
int i1 = in[ip++];
|
||||
int i2 = ip < iEnd ? in[ip++] : 'A';
|
||||
int i3 = ip < iEnd ? in[ip++] : 'A';
|
||||
if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127)
|
||||
throw new IllegalArgumentException("Illegal character in Base64 encoded data.");
|
||||
int b0 = map2[i0];
|
||||
int b1 = map2[i1];
|
||||
int b2 = map2[i2];
|
||||
int b3 = map2[i3];
|
||||
if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0)
|
||||
throw new IllegalArgumentException("Illegal character in Base64 encoded data.");
|
||||
int o0 = (b0 << 2) | (b1 >>> 4);
|
||||
int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2);
|
||||
int o2 = ((b2 & 3) << 6) | b3;
|
||||
out[op++] = (byte) o0;
|
||||
if (op < oLen)
|
||||
out[op++] = (byte) o1;
|
||||
if (op < oLen)
|
||||
out[op++] = (byte) o2;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Dummy constructor.
|
||||
private Base64Coder() {
|
||||
}
|
||||
|
||||
} // end class Base64Coder
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/* Copyright (c) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.jenkins.plugins.casc.snakeyaml.external.com.google.gdata.util.common.base;
|
||||
|
||||
/**
|
||||
* An object that converts literal text into a format safe for inclusion in a
|
||||
* particular context (such as an XML document). Typically (but not always), the
|
||||
* inverse process of "unescaping" the text is performed automatically by the
|
||||
* relevant parser.
|
||||
*
|
||||
* <p>
|
||||
* For example, an XML escaper would convert the literal string
|
||||
* {@code "Foo<Bar>"} into {@code "Foo<Bar>"} to prevent {@code "<Bar>"}
|
||||
* from being confused with an XML tag. When the resulting XML document is
|
||||
* parsed, the parser API will return this text as the original literal string
|
||||
* {@code "Foo<Bar>"}.
|
||||
*
|
||||
* <p>
|
||||
* An {@code Escaper} instance is required to be stateless, and safe when used
|
||||
* concurrently by multiple threads.
|
||||
*
|
||||
* <p>
|
||||
* Several popular escapers are defined as constants in the class
|
||||
* {@link CharEscapers}. To create your own escapers, use
|
||||
* {@link CharEscaperBuilder}, or extend {@link CharEscaper} or
|
||||
* {@code UnicodeEscaper}.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface Escaper {
|
||||
/**
|
||||
* Returns the escaped form of a given literal string.
|
||||
*
|
||||
* <p>
|
||||
* Note that this method may treat input characters differently depending on
|
||||
* the specific escaper implementation.
|
||||
* <ul>
|
||||
* <li>{@link UnicodeEscaper} handles <a
|
||||
* href="http://en.wikipedia.org/wiki/UTF-16">UTF-16</a> correctly,
|
||||
* including surrogate character pairs. If the input is badly formed the
|
||||
* escaper should throw {@link IllegalArgumentException}.
|
||||
* <li>{@link CharEscaper} handles Java characters independently and does
|
||||
* not verify the input for well formed characters. A CharEscaper should not
|
||||
* be used in situations where input is not guaranteed to be restricted to
|
||||
* the Basic Multilingual Plane (BMP).
|
||||
* </ul>
|
||||
*
|
||||
* @param string
|
||||
* the literal string to be escaped
|
||||
* @return the escaped form of {@code string}
|
||||
* @throws NullPointerException
|
||||
* if {@code string} is null
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code string} contains badly formed UTF-16 or cannot be
|
||||
* escaped for any other reason
|
||||
*/
|
||||
public String escape(String string);
|
||||
|
||||
/**
|
||||
* Returns an {@code Appendable} instance which automatically escapes all
|
||||
* text appended to it before passing the resulting text to an underlying
|
||||
* {@code Appendable}.
|
||||
*
|
||||
* <p>
|
||||
* Note that this method may treat input characters differently depending on
|
||||
* the specific escaper implementation.
|
||||
* <ul>
|
||||
* <li>{@link UnicodeEscaper} handles <a
|
||||
* href="http://en.wikipedia.org/wiki/UTF-16">UTF-16</a> correctly,
|
||||
* including surrogate character pairs. If the input is badly formed the
|
||||
* escaper should throw {@link IllegalArgumentException}.
|
||||
* <li>{@link CharEscaper} handles Java characters independently and does
|
||||
* not verify the input for well formed characters. A CharEscaper should not
|
||||
* be used in situations where input is not guaranteed to be restricted to
|
||||
* the Basic Multilingual Plane (BMP).
|
||||
* </ul>
|
||||
*
|
||||
* @param out
|
||||
* the underlying {@code Appendable} to append escaped output to
|
||||
* @return an {@code Appendable} which passes text to {@code out} after
|
||||
* escaping it.
|
||||
*/
|
||||
public Appendable escape(Appendable out);
|
||||
}
|
||||
|
|
@ -0,0 +1,281 @@
|
|||
/* Copyright (c) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.jenkins.plugins.casc.snakeyaml.external.com.google.gdata.util.common.base;
|
||||
|
||||
/**
|
||||
* A {@code UnicodeEscaper} that escapes some set of Java characters using the
|
||||
* URI percent encoding scheme. The set of safe characters (those which remain
|
||||
* unescaped) can be specified on construction.
|
||||
*
|
||||
* <p>
|
||||
* For details on escaping URIs for use in web pages, see section 2.4 of <a
|
||||
* href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>.
|
||||
*
|
||||
* <p>
|
||||
* In most cases this class should not need to be used directly. If you have no
|
||||
* special requirements for escaping your URIs, you should use either
|
||||
* {@link CharEscapers#uriEscaper()} or {@link CharEscapers#uriEscaper(boolean)}.
|
||||
*
|
||||
* <p>
|
||||
* When encoding a String, the following rules apply:
|
||||
* <ul>
|
||||
* <li>The alphanumeric characters "a" through "z", "A" through "Z" and "0"
|
||||
* through "9" remain the same.
|
||||
* <li>Any additionally specified safe characters remain the same.
|
||||
* <li>If {@code plusForSpace} was specified, the space character " " is
|
||||
* converted into a plus sign "+".
|
||||
* <li>All other characters are converted into one or more bytes using UTF-8
|
||||
* encoding and each byte is then represented by the 3-character string "%XY",
|
||||
* where "XY" is the two-digit, uppercase, hexadecimal representation of the
|
||||
* byte value.
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* RFC 2396 specifies the set of unreserved characters as "-", "_", ".", "!",
|
||||
* "~", "*", "'", "(" and ")". It goes on to state:
|
||||
*
|
||||
* <p>
|
||||
* <i>Unreserved characters can be escaped without changing the semantics of the
|
||||
* URI, but this should not be done unless the URI is being used in a context
|
||||
* that does not allow the unescaped character to appear.</i>
|
||||
*
|
||||
* <p>
|
||||
* For performance reasons the only currently supported character encoding of
|
||||
* this class is UTF-8.
|
||||
*
|
||||
* <p>
|
||||
* <b>Note</b>: This escaper produces uppercase hexidecimal sequences. From <a
|
||||
* href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>:<br>
|
||||
* <i>"URI producers and normalizers should use uppercase hexadecimal digits for
|
||||
* all percent-encodings."</i>
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class PercentEscaper extends UnicodeEscaper {
|
||||
/**
|
||||
* A string of safe characters that mimics the behavior of
|
||||
* {@link java.net.URLEncoder}.
|
||||
*
|
||||
*/
|
||||
public static final String SAFECHARS_URLENCODER = "-_.*";
|
||||
|
||||
/**
|
||||
* A string of characters that do not need to be encoded when used in URI
|
||||
* path segments, as specified in RFC 3986. Note that some of these
|
||||
* characters do need to be escaped when used in other parts of the URI.
|
||||
*/
|
||||
public static final String SAFEPATHCHARS_URLENCODER = "-_.!~*'()@:$&,;=";
|
||||
|
||||
/**
|
||||
* A string of characters that do not need to be encoded when used in URI
|
||||
* query strings, as specified in RFC 3986. Note that some of these
|
||||
* characters do need to be escaped when used in other parts of the URI.
|
||||
*/
|
||||
public static final String SAFEQUERYSTRINGCHARS_URLENCODER = "-_.!~*'()@:$,;/?:";
|
||||
|
||||
// In some uri escapers spaces are escaped to '+'
|
||||
private static final char[] URI_ESCAPED_SPACE = { '+' };
|
||||
|
||||
private static final char[] UPPER_HEX_DIGITS = "0123456789ABCDEF".toCharArray();
|
||||
|
||||
/**
|
||||
* If true we should convert space to the {@code +} character.
|
||||
*/
|
||||
private final boolean plusForSpace;
|
||||
|
||||
/**
|
||||
* An array of flags where for any {@code char c} if {@code safeOctets[c]}
|
||||
* is true then {@code c} should remain unmodified in the output. If
|
||||
* {@code c > safeOctets.length} then it should be escaped.
|
||||
*/
|
||||
private final boolean[] safeOctets;
|
||||
|
||||
/**
|
||||
* Constructs a URI escaper with the specified safe characters and optional
|
||||
* handling of the space character.
|
||||
*
|
||||
* @param safeChars
|
||||
* a non null string specifying additional safe characters for
|
||||
* this escaper (the ranges 0..9, a..z and A..Z are always safe
|
||||
* and should not be specified here)
|
||||
* @param plusForSpace
|
||||
* true if ASCII space should be escaped to {@code +} rather than
|
||||
* {@code %20}
|
||||
* @throws IllegalArgumentException
|
||||
* if any of the parameters were invalid
|
||||
*/
|
||||
public PercentEscaper(String safeChars, boolean plusForSpace) {
|
||||
// Avoid any misunderstandings about the behavior of this escaper
|
||||
if (safeChars.matches(".*[0-9A-Za-z].*")) {
|
||||
throw new IllegalArgumentException(
|
||||
"Alphanumeric characters are always 'safe' and should not be "
|
||||
+ "explicitly specified");
|
||||
}
|
||||
// Avoid ambiguous parameters. Safe characters are never modified so if
|
||||
// space is a safe character then setting plusForSpace is meaningless.
|
||||
if (plusForSpace && safeChars.contains(" ")) {
|
||||
throw new IllegalArgumentException(
|
||||
"plusForSpace cannot be specified when space is a 'safe' character");
|
||||
}
|
||||
if (safeChars.contains("%")) {
|
||||
throw new IllegalArgumentException("The '%' character cannot be specified as 'safe'");
|
||||
}
|
||||
this.plusForSpace = plusForSpace;
|
||||
this.safeOctets = createSafeOctets(safeChars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a boolean[] with entries corresponding to the character values
|
||||
* for 0-9, A-Z, a-z and those specified in safeChars set to true. The array
|
||||
* is as small as is required to hold the given character information.
|
||||
*/
|
||||
private static boolean[] createSafeOctets(String safeChars) {
|
||||
int maxChar = 'z';
|
||||
char[] safeCharArray = safeChars.toCharArray();
|
||||
for (char c : safeCharArray) {
|
||||
maxChar = Math.max(c, maxChar);
|
||||
}
|
||||
boolean[] octets = new boolean[maxChar + 1];
|
||||
for (int c = '0'; c <= '9'; c++) {
|
||||
octets[c] = true;
|
||||
}
|
||||
for (int c = 'A'; c <= 'Z'; c++) {
|
||||
octets[c] = true;
|
||||
}
|
||||
for (int c = 'a'; c <= 'z'; c++) {
|
||||
octets[c] = true;
|
||||
}
|
||||
for (char c : safeCharArray) {
|
||||
octets[c] = true;
|
||||
}
|
||||
return octets;
|
||||
}
|
||||
|
||||
/*
|
||||
* Overridden for performance. For unescaped strings this improved the
|
||||
* performance of the uri escaper from ~760ns to ~400ns as measured by
|
||||
* {@link CharEscapersBenchmark}.
|
||||
*/
|
||||
@Override
|
||||
protected int nextEscapeIndex(CharSequence csq, int index, int end) {
|
||||
for (; index < end; index++) {
|
||||
char c = csq.charAt(index);
|
||||
if (c >= safeOctets.length || !safeOctets[c]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/*
|
||||
* Overridden for performance. For unescaped strings this improved the
|
||||
* performance of the uri escaper from ~400ns to ~170ns as measured by
|
||||
* {@link CharEscapersBenchmark}.
|
||||
*/
|
||||
@Override
|
||||
public String escape(String s) {
|
||||
int slen = s.length();
|
||||
for (int index = 0; index < slen; index++) {
|
||||
char c = s.charAt(index);
|
||||
if (c >= safeOctets.length || !safeOctets[c]) {
|
||||
return escapeSlow(s, index);
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes the given Unicode code point in UTF-8.
|
||||
*/
|
||||
@Override
|
||||
protected char[] escape(int cp) {
|
||||
// We should never get negative values here but if we do it will throw
|
||||
// an
|
||||
// IndexOutOfBoundsException, so at least it will get spotted.
|
||||
if (cp < safeOctets.length && safeOctets[cp]) {
|
||||
return null;
|
||||
} else if (cp == ' ' && plusForSpace) {
|
||||
return URI_ESCAPED_SPACE;
|
||||
} else if (cp <= 0x7F) {
|
||||
// Single byte UTF-8 characters
|
||||
// Start with "%--" and fill in the blanks
|
||||
char[] dest = new char[3];
|
||||
dest[0] = '%';
|
||||
dest[2] = UPPER_HEX_DIGITS[cp & 0xF];
|
||||
dest[1] = UPPER_HEX_DIGITS[cp >>> 4];
|
||||
return dest;
|
||||
} else if (cp <= 0x7ff) {
|
||||
// Two byte UTF-8 characters [cp >= 0x80 && cp <= 0x7ff]
|
||||
// Start with "%--%--" and fill in the blanks
|
||||
char[] dest = new char[6];
|
||||
dest[0] = '%';
|
||||
dest[3] = '%';
|
||||
dest[5] = UPPER_HEX_DIGITS[cp & 0xF];
|
||||
cp >>>= 4;
|
||||
dest[4] = UPPER_HEX_DIGITS[0x8 | (cp & 0x3)];
|
||||
cp >>>= 2;
|
||||
dest[2] = UPPER_HEX_DIGITS[cp & 0xF];
|
||||
cp >>>= 4;
|
||||
dest[1] = UPPER_HEX_DIGITS[0xC | cp];
|
||||
return dest;
|
||||
} else if (cp <= 0xffff) {
|
||||
// Three byte UTF-8 characters [cp >= 0x800 && cp <= 0xffff]
|
||||
// Start with "%E-%--%--" and fill in the blanks
|
||||
char[] dest = new char[9];
|
||||
dest[0] = '%';
|
||||
dest[1] = 'E';
|
||||
dest[3] = '%';
|
||||
dest[6] = '%';
|
||||
dest[8] = UPPER_HEX_DIGITS[cp & 0xF];
|
||||
cp >>>= 4;
|
||||
dest[7] = UPPER_HEX_DIGITS[0x8 | (cp & 0x3)];
|
||||
cp >>>= 2;
|
||||
dest[5] = UPPER_HEX_DIGITS[cp & 0xF];
|
||||
cp >>>= 4;
|
||||
dest[4] = UPPER_HEX_DIGITS[0x8 | (cp & 0x3)];
|
||||
cp >>>= 2;
|
||||
dest[2] = UPPER_HEX_DIGITS[cp];
|
||||
return dest;
|
||||
} else if (cp <= 0x10ffff) {
|
||||
char[] dest = new char[12];
|
||||
// Four byte UTF-8 characters [cp >= 0xffff && cp <= 0x10ffff]
|
||||
// Start with "%F-%--%--%--" and fill in the blanks
|
||||
dest[0] = '%';
|
||||
dest[1] = 'F';
|
||||
dest[3] = '%';
|
||||
dest[6] = '%';
|
||||
dest[9] = '%';
|
||||
dest[11] = UPPER_HEX_DIGITS[cp & 0xF];
|
||||
cp >>>= 4;
|
||||
dest[10] = UPPER_HEX_DIGITS[0x8 | (cp & 0x3)];
|
||||
cp >>>= 2;
|
||||
dest[8] = UPPER_HEX_DIGITS[cp & 0xF];
|
||||
cp >>>= 4;
|
||||
dest[7] = UPPER_HEX_DIGITS[0x8 | (cp & 0x3)];
|
||||
cp >>>= 2;
|
||||
dest[5] = UPPER_HEX_DIGITS[cp & 0xF];
|
||||
cp >>>= 4;
|
||||
dest[4] = UPPER_HEX_DIGITS[0x8 | (cp & 0x3)];
|
||||
cp >>>= 2;
|
||||
dest[2] = UPPER_HEX_DIGITS[cp & 0x7];
|
||||
return dest;
|
||||
} else {
|
||||
// If this ever happens it is due to bug in UnicodeEscaper, not bad
|
||||
// input.
|
||||
throw new IllegalArgumentException("Invalid unicode character value " + cp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,506 @@
|
|||
/* Copyright (c) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.jenkins.plugins.casc.snakeyaml.external.com.google.gdata.util.common.base;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* An {@link Escaper} that converts literal text into a format safe for
|
||||
* inclusion in a particular context (such as an XML document). Typically (but
|
||||
* not always), the inverse process of "unescaping" the text is performed
|
||||
* automatically by the relevant parser.
|
||||
*
|
||||
* <p>
|
||||
* For example, an XML escaper would convert the literal string
|
||||
* {@code "Foo<Bar>"} into {@code "Foo<Bar>"} to prevent {@code "<Bar>"}
|
||||
* from being confused with an XML tag. When the resulting XML document is
|
||||
* parsed, the parser API will return this text as the original literal string
|
||||
* {@code "Foo<Bar>"}.
|
||||
*
|
||||
* <p>
|
||||
* <b>Note:</b> This class is similar to {@link CharEscaper} but with one very
|
||||
* important difference. A CharEscaper can only process Java <a
|
||||
* href="http://en.wikipedia.org/wiki/UTF-16">UTF16</a> characters in isolation
|
||||
* and may not cope when it encounters surrogate pairs. This class facilitates
|
||||
* the correct escaping of all Unicode characters.
|
||||
*
|
||||
* <p>
|
||||
* As there are important reasons, including potential security issues, to
|
||||
* handle Unicode correctly if you are considering implementing a new escaper
|
||||
* you should favor using UnicodeEscaper wherever possible.
|
||||
*
|
||||
* <p>
|
||||
* A {@code UnicodeEscaper} instance is required to be stateless, and safe when
|
||||
* used concurrently by multiple threads.
|
||||
*
|
||||
* <p>
|
||||
* Several popular escapers are defined as constants in the class
|
||||
* {@link CharEscapers}. To create your own escapers extend this class and
|
||||
* implement the {@link #escape(int)} method.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public abstract class UnicodeEscaper implements Escaper {
|
||||
/** The amount of padding (chars) to use when growing the escape buffer. */
|
||||
private static final int DEST_PAD = 32;
|
||||
|
||||
/**
|
||||
* Returns the escaped form of the given Unicode code point, or {@code null}
|
||||
* if this code point does not need to be escaped. When called as part of an
|
||||
* escaping operation, the given code point is guaranteed to be in the range
|
||||
* {@code 0 <= cp <= Character#MAX_CODE_POINT}.
|
||||
*
|
||||
* <p>
|
||||
* If an empty array is returned, this effectively strips the input
|
||||
* character from the resulting text.
|
||||
*
|
||||
* <p>
|
||||
* If the character does not need to be escaped, this method should return
|
||||
* {@code null}, rather than an array containing the character
|
||||
* representation of the code point. This enables the escaping algorithm to
|
||||
* perform more efficiently.
|
||||
*
|
||||
* <p>
|
||||
* If the implementation of this method cannot correctly handle a particular
|
||||
* code point then it should either throw an appropriate runtime exception
|
||||
* or return a suitable replacement character. It must never silently
|
||||
* discard invalid input as this may constitute a security risk.
|
||||
*
|
||||
* @param cp
|
||||
* the Unicode code point to escape if necessary
|
||||
* @return the replacement characters, or {@code null} if no escaping was
|
||||
* needed
|
||||
*/
|
||||
protected abstract char[] escape(int cp);
|
||||
|
||||
/**
|
||||
* Scans a sub-sequence of characters from a given {@link CharSequence},
|
||||
* returning the index of the next character that requires escaping.
|
||||
*
|
||||
* <p>
|
||||
* <b>Note:</b> When implementing an escaper, it is a good idea to override
|
||||
* this method for efficiency. The base class implementation determines
|
||||
* successive Unicode code points and invokes {@link #escape(int)} for each
|
||||
* of them. If the semantics of your escaper are such that code points in
|
||||
* the supplementary range are either all escaped or all unescaped, this
|
||||
* method can be implemented more efficiently using
|
||||
* {@link CharSequence#charAt(int)}.
|
||||
*
|
||||
* <p>
|
||||
* Note however that if your escaper does not escape characters in the
|
||||
* supplementary range, you should either continue to validate the
|
||||
* correctness of any surrogate characters encountered or provide a clear
|
||||
* warning to users that your escaper does not validate its input.
|
||||
*
|
||||
* <p>
|
||||
* See {@link PercentEscaper} for an example.
|
||||
*
|
||||
* @param csq
|
||||
* a sequence of characters
|
||||
* @param start
|
||||
* the index of the first character to be scanned
|
||||
* @param end
|
||||
* the index immediately after the last character to be scanned
|
||||
* @throws IllegalArgumentException
|
||||
* if the scanned sub-sequence of {@code csq} contains invalid
|
||||
* surrogate pairs
|
||||
*/
|
||||
protected int nextEscapeIndex(CharSequence csq, int start, int end) {
|
||||
int index = start;
|
||||
while (index < end) {
|
||||
int cp = codePointAt(csq, index, end);
|
||||
if (cp < 0 || escape(cp) != null) {
|
||||
break;
|
||||
}
|
||||
index += Character.isSupplementaryCodePoint(cp) ? 2 : 1;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the escaped form of a given literal string.
|
||||
*
|
||||
* <p>
|
||||
* If you are escaping input in arbitrary successive chunks, then it is not
|
||||
* generally safe to use this method. If an input string ends with an
|
||||
* unmatched high surrogate character, then this method will throw
|
||||
* {@link IllegalArgumentException}. You should either ensure your input is
|
||||
* valid <a href="http://en.wikipedia.org/wiki/UTF-16">UTF-16</a> before
|
||||
* calling this method or use an escaped {@link Appendable} (as returned by
|
||||
* {@link #escape(Appendable)}) which can cope with arbitrarily split input.
|
||||
*
|
||||
* <p>
|
||||
* <b>Note:</b> When implementing an escaper it is a good idea to override
|
||||
* this method for efficiency by inlining the implementation of
|
||||
* {@link #nextEscapeIndex(CharSequence, int, int)} directly. Doing this for
|
||||
* {@link PercentEscaper} more than doubled the performance for unescaped
|
||||
* strings (as measured by {@link CharEscapersBenchmark}).
|
||||
*
|
||||
* @param string
|
||||
* the literal string to be escaped
|
||||
* @return the escaped form of {@code string}
|
||||
* @throws NullPointerException
|
||||
* if {@code string} is null
|
||||
* @throws IllegalArgumentException
|
||||
* if invalid surrogate characters are encountered
|
||||
*/
|
||||
public String escape(String string) {
|
||||
int end = string.length();
|
||||
int index = nextEscapeIndex(string, 0, end);
|
||||
return index == end ? string : escapeSlow(string, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the escaped form of a given literal string, starting at the given
|
||||
* index. This method is called by the {@link #escape(String)} method when
|
||||
* it discovers that escaping is required. It is protected to allow
|
||||
* subclasses to override the fastpath escaping function to inline their
|
||||
* escaping test. See {@link CharEscaperBuilder} for an example usage.
|
||||
*
|
||||
* <p>
|
||||
* This method is not reentrant and may only be invoked by the top level
|
||||
* {@link #escape(String)} method.
|
||||
*
|
||||
* @param s
|
||||
* the literal string to be escaped
|
||||
* @param index
|
||||
* the index to start escaping from
|
||||
* @return the escaped form of {@code string}
|
||||
* @throws NullPointerException
|
||||
* if {@code string} is null
|
||||
* @throws IllegalArgumentException
|
||||
* if invalid surrogate characters are encountered
|
||||
*/
|
||||
protected final String escapeSlow(String s, int index) {
|
||||
int end = s.length();
|
||||
|
||||
// Get a destination buffer and setup some loop variables.
|
||||
char[] dest = DEST_TL.get();
|
||||
int destIndex = 0;
|
||||
int unescapedChunkStart = 0;
|
||||
|
||||
while (index < end) {
|
||||
int cp = codePointAt(s, index, end);
|
||||
if (cp < 0) {
|
||||
throw new IllegalArgumentException("Trailing high surrogate at end of input");
|
||||
}
|
||||
char[] escaped = escape(cp);
|
||||
if (escaped != null) {
|
||||
int charsSkipped = index - unescapedChunkStart;
|
||||
|
||||
// This is the size needed to add the replacement, not the full
|
||||
// size needed by the string. We only regrow when we absolutely
|
||||
// must.
|
||||
int sizeNeeded = destIndex + charsSkipped + escaped.length;
|
||||
if (dest.length < sizeNeeded) {
|
||||
int destLength = sizeNeeded + (end - index) + DEST_PAD;
|
||||
dest = growBuffer(dest, destIndex, destLength);
|
||||
}
|
||||
// If we have skipped any characters, we need to copy them now.
|
||||
if (charsSkipped > 0) {
|
||||
s.getChars(unescapedChunkStart, index, dest, destIndex);
|
||||
destIndex += charsSkipped;
|
||||
}
|
||||
if (escaped.length > 0) {
|
||||
System.arraycopy(escaped, 0, dest, destIndex, escaped.length);
|
||||
destIndex += escaped.length;
|
||||
}
|
||||
}
|
||||
unescapedChunkStart = index + (Character.isSupplementaryCodePoint(cp) ? 2 : 1);
|
||||
index = nextEscapeIndex(s, unescapedChunkStart, end);
|
||||
}
|
||||
|
||||
// Process trailing unescaped characters - no need to account for
|
||||
// escaped
|
||||
// length or padding the allocation.
|
||||
int charsSkipped = end - unescapedChunkStart;
|
||||
if (charsSkipped > 0) {
|
||||
int endIndex = destIndex + charsSkipped;
|
||||
if (dest.length < endIndex) {
|
||||
dest = growBuffer(dest, destIndex, endIndex);
|
||||
}
|
||||
s.getChars(unescapedChunkStart, end, dest, destIndex);
|
||||
destIndex = endIndex;
|
||||
}
|
||||
return new String(dest, 0, destIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@code Appendable} instance which automatically escapes all
|
||||
* text appended to it before passing the resulting text to an underlying
|
||||
* {@code Appendable}.
|
||||
*
|
||||
* <p>
|
||||
* Unlike {@link #escape(String)} it is permitted to append arbitrarily
|
||||
* split input to this Appendable, including input that is split over a
|
||||
* surrogate pair. In this case the pending high surrogate character will
|
||||
* not be processed until the corresponding low surrogate is appended. This
|
||||
* means that a trailing high surrogate character at the end of the input
|
||||
* cannot be detected and will be silently ignored. This is unavoidable
|
||||
* since the Appendable interface has no {@code close()} method, and it is
|
||||
* impossible to determine when the last characters have been appended.
|
||||
*
|
||||
* <p>
|
||||
* The methods of the returned object will propagate any exceptions thrown
|
||||
* by the underlying {@code Appendable}.
|
||||
*
|
||||
* <p>
|
||||
* For well formed <a href="http://en.wikipedia.org/wiki/UTF-16">UTF-16</a>
|
||||
* the escaping behavior is identical to that of {@link #escape(String)} and
|
||||
* the following code is equivalent to (but much slower than)
|
||||
* {@code escaper.escape(string)}:
|
||||
*
|
||||
* <pre>
|
||||
* {
|
||||
* @code
|
||||
* StringBuilder sb = new StringBuilder();
|
||||
* escaper.escape(sb).append(string);
|
||||
* return sb.toString();
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param out
|
||||
* the underlying {@code Appendable} to append escaped output to
|
||||
* @return an {@code Appendable} which passes text to {@code out} after
|
||||
* escaping it
|
||||
* @throws NullPointerException
|
||||
* if {@code out} is null
|
||||
* @throws IllegalArgumentException
|
||||
* if invalid surrogate characters are encountered
|
||||
*
|
||||
*/
|
||||
public Appendable escape(final Appendable out) {
|
||||
assert out != null;
|
||||
|
||||
return new Appendable() {
|
||||
int pendingHighSurrogate = -1;
|
||||
char[] decodedChars = new char[2];
|
||||
|
||||
public Appendable append(CharSequence csq) throws IOException {
|
||||
return append(csq, 0, csq.length());
|
||||
}
|
||||
|
||||
public Appendable append(CharSequence csq, int start, int end) throws IOException {
|
||||
int index = start;
|
||||
if (index < end) {
|
||||
// This is a little subtle: index must never reference the
|
||||
// middle of a
|
||||
// surrogate pair but unescapedChunkStart can. The first
|
||||
// time we enter
|
||||
// the loop below it is possible that index !=
|
||||
// unescapedChunkStart.
|
||||
int unescapedChunkStart = index;
|
||||
if (pendingHighSurrogate != -1) {
|
||||
// Our last append operation ended halfway through a
|
||||
// surrogate pair
|
||||
// so we have to do some extra work first.
|
||||
char c = csq.charAt(index++);
|
||||
if (!Character.isLowSurrogate(c)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Expected low surrogate character but got " + c);
|
||||
}
|
||||
char[] escaped = escape(Character.toCodePoint((char) pendingHighSurrogate,
|
||||
c));
|
||||
if (escaped != null) {
|
||||
// Emit the escaped character and adjust
|
||||
// unescapedChunkStart to
|
||||
// skip the low surrogate we have consumed.
|
||||
outputChars(escaped, escaped.length);
|
||||
unescapedChunkStart += 1;
|
||||
} else {
|
||||
// Emit pending high surrogate (unescaped) but do
|
||||
// not modify
|
||||
// unescapedChunkStart as we must still emit the low
|
||||
// surrogate.
|
||||
out.append((char) pendingHighSurrogate);
|
||||
}
|
||||
pendingHighSurrogate = -1;
|
||||
}
|
||||
while (true) {
|
||||
// Find and append the next subsequence of unescaped
|
||||
// characters.
|
||||
index = nextEscapeIndex(csq, index, end);
|
||||
if (index > unescapedChunkStart) {
|
||||
out.append(csq, unescapedChunkStart, index);
|
||||
}
|
||||
if (index == end) {
|
||||
break;
|
||||
}
|
||||
// If we are not finished, calculate the next code
|
||||
// point.
|
||||
int cp = codePointAt(csq, index, end);
|
||||
if (cp < 0) {
|
||||
// Our sequence ended half way through a surrogate
|
||||
// pair so just
|
||||
// record the state and exit.
|
||||
pendingHighSurrogate = -cp;
|
||||
break;
|
||||
}
|
||||
// Escape the code point and output the characters.
|
||||
char[] escaped = escape(cp);
|
||||
if (escaped != null) {
|
||||
outputChars(escaped, escaped.length);
|
||||
} else {
|
||||
// This shouldn't really happen if nextEscapeIndex
|
||||
// is correct but
|
||||
// we should cope with false positives.
|
||||
int len = Character.toChars(cp, decodedChars, 0);
|
||||
outputChars(decodedChars, len);
|
||||
}
|
||||
// Update our index past the escaped character and
|
||||
// continue.
|
||||
index += (Character.isSupplementaryCodePoint(cp) ? 2 : 1);
|
||||
unescapedChunkStart = index;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Appendable append(char c) throws IOException {
|
||||
if (pendingHighSurrogate != -1) {
|
||||
// Our last append operation ended halfway through a
|
||||
// surrogate pair
|
||||
// so we have to do some extra work first.
|
||||
if (!Character.isLowSurrogate(c)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Expected low surrogate character but got '" + c + "' with value "
|
||||
+ (int) c);
|
||||
}
|
||||
char[] escaped = escape(Character.toCodePoint((char) pendingHighSurrogate, c));
|
||||
if (escaped != null) {
|
||||
outputChars(escaped, escaped.length);
|
||||
} else {
|
||||
out.append((char) pendingHighSurrogate);
|
||||
out.append(c);
|
||||
}
|
||||
pendingHighSurrogate = -1;
|
||||
} else if (Character.isHighSurrogate(c)) {
|
||||
// This is the start of a (split) surrogate pair.
|
||||
pendingHighSurrogate = c;
|
||||
} else {
|
||||
if (Character.isLowSurrogate(c)) {
|
||||
throw new IllegalArgumentException("Unexpected low surrogate character '"
|
||||
+ c + "' with value " + (int) c);
|
||||
}
|
||||
// This is a normal (non surrogate) char.
|
||||
char[] escaped = escape(c);
|
||||
if (escaped != null) {
|
||||
outputChars(escaped, escaped.length);
|
||||
} else {
|
||||
out.append(c);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private void outputChars(char[] chars, int len) throws IOException {
|
||||
for (int n = 0; n < len; n++) {
|
||||
out.append(chars[n]);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Unicode code point of the character at the given index.
|
||||
*
|
||||
* <p>
|
||||
* Unlike {@link Character#codePointAt(CharSequence, int)} or
|
||||
* {@link String#codePointAt(int)} this method will never fail silently when
|
||||
* encountering an invalid surrogate pair.
|
||||
*
|
||||
* <p>
|
||||
* The behaviour of this method is as follows:
|
||||
* <ol>
|
||||
* <li>If {@code index >= end}, {@link IndexOutOfBoundsException} is thrown.
|
||||
* <li><b>If the character at the specified index is not a surrogate, it is
|
||||
* returned.</b>
|
||||
* <li>If the first character was a high surrogate value, then an attempt is
|
||||
* made to read the next character.
|
||||
* <ol>
|
||||
* <li><b>If the end of the sequence was reached, the negated value of the
|
||||
* trailing high surrogate is returned.</b>
|
||||
* <li><b>If the next character was a valid low surrogate, the code point
|
||||
* value of the high/low surrogate pair is returned.</b>
|
||||
* <li>If the next character was not a low surrogate value, then
|
||||
* {@link IllegalArgumentException} is thrown.
|
||||
* </ol>
|
||||
* <li>If the first character was a low surrogate value,
|
||||
* {@link IllegalArgumentException} is thrown.
|
||||
* </ol>
|
||||
*
|
||||
* @param seq
|
||||
* the sequence of characters from which to decode the code point
|
||||
* @param index
|
||||
* the index of the first character to decode
|
||||
* @param end
|
||||
* the index beyond the last valid character to decode
|
||||
* @return the Unicode code point for the given index or the negated value
|
||||
* of the trailing high surrogate character at the end of the
|
||||
* sequence
|
||||
*/
|
||||
protected static final int codePointAt(CharSequence seq, int index, int end) {
|
||||
if (index < end) {
|
||||
char c1 = seq.charAt(index++);
|
||||
if (c1 < Character.MIN_HIGH_SURROGATE || c1 > Character.MAX_LOW_SURROGATE) {
|
||||
// Fast path (first test is probably all we need to do)
|
||||
return c1;
|
||||
} else if (c1 <= Character.MAX_HIGH_SURROGATE) {
|
||||
// If the high surrogate was the last character, return its
|
||||
// inverse
|
||||
if (index == end) {
|
||||
return -c1;
|
||||
}
|
||||
// Otherwise look for the low surrogate following it
|
||||
char c2 = seq.charAt(index);
|
||||
if (Character.isLowSurrogate(c2)) {
|
||||
return Character.toCodePoint(c1, c2);
|
||||
}
|
||||
throw new IllegalArgumentException("Expected low surrogate but got char '" + c2
|
||||
+ "' with value " + (int) c2 + " at index " + index);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unexpected low surrogate character '" + c1
|
||||
+ "' with value " + (int) c1 + " at index " + (index - 1));
|
||||
}
|
||||
}
|
||||
throw new IndexOutOfBoundsException("Index exceeds specified range");
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to grow the character buffer as needed, this only happens
|
||||
* once in a while so it's ok if it's in a method call. If the index passed
|
||||
* in is 0 then no copying will be done.
|
||||
*/
|
||||
private static final char[] growBuffer(char[] dest, int index, int size) {
|
||||
char[] copy = new char[size];
|
||||
if (index > 0) {
|
||||
System.arraycopy(dest, 0, copy, 0, index);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* A thread-local destination buffer to keep us from creating new buffers.
|
||||
* The starting size is 1024 characters. If we grow past this we don't put
|
||||
* it back in the threadlocal, we just keep going and grow as needed.
|
||||
*/
|
||||
private static final ThreadLocal<char[]> DEST_TL = new ThreadLocal<char[]>() {
|
||||
@Override
|
||||
protected char[] initialValue() {
|
||||
return new char[1024];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.introspector;
|
||||
|
||||
/**
|
||||
* Control instance variables.
|
||||
*/
|
||||
public enum BeanAccess {
|
||||
/** use JavaBean properties and public fields */
|
||||
DEFAULT,
|
||||
|
||||
/** use all declared fields (including inherited) */
|
||||
FIELD,
|
||||
|
||||
/** reserved */
|
||||
PROPERTY;
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.introspector;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.YAMLException;
|
||||
import io.jenkins.plugins.casc.snakeyaml.util.ArrayUtils;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A <code>FieldProperty</code> is a <code>Property</code> which is accessed as
|
||||
* a field, without going through accessor methods (setX, getX). The field may
|
||||
* have any scope (public, package, protected, private).
|
||||
* </p>
|
||||
*/
|
||||
public class FieldProperty extends GenericProperty {
|
||||
|
||||
private final Field field;
|
||||
|
||||
public FieldProperty(Field field) {
|
||||
super(field.getName(), field.getType(), field.getGenericType());
|
||||
this.field = field;
|
||||
field.setAccessible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(Object object, Object value) throws Exception {
|
||||
field.set(object, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(Object object) {
|
||||
try {
|
||||
return field.get(object);
|
||||
} catch (Exception e) {
|
||||
throw new YAMLException("Unable to access field " + field.getName() + " on object "
|
||||
+ object + " : " + e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Annotation> getAnnotations() {
|
||||
return ArrayUtils.toUnmodifiableList(field.getAnnotations());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
|
||||
return field.getAnnotation(annotationType);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.introspector;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
abstract public class GenericProperty extends Property {
|
||||
|
||||
private Type genType;
|
||||
|
||||
public GenericProperty(String name, Class<?> aClass, Type aType) {
|
||||
super(name, aClass);
|
||||
genType = aType;
|
||||
actualClassesChecked = aType == null;
|
||||
}
|
||||
|
||||
private boolean actualClassesChecked;
|
||||
private Class<?>[] actualClasses;
|
||||
|
||||
public Class<?>[] getActualTypeArguments() { // should we synchronize here ?
|
||||
if (!actualClassesChecked) {
|
||||
if (genType instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedType = (ParameterizedType) genType;
|
||||
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
|
||||
if (actualTypeArguments.length > 0) {
|
||||
actualClasses = new Class<?>[actualTypeArguments.length];
|
||||
for (int i = 0; i < actualTypeArguments.length; i++) {
|
||||
if (actualTypeArguments[i] instanceof Class<?>) {
|
||||
actualClasses[i] = (Class<?>) actualTypeArguments[i];
|
||||
} else if (actualTypeArguments[i] instanceof ParameterizedType) {
|
||||
actualClasses[i] = (Class<?>) ((ParameterizedType) actualTypeArguments[i])
|
||||
.getRawType();
|
||||
} else if (actualTypeArguments[i] instanceof GenericArrayType) {
|
||||
Type componentType = ((GenericArrayType) actualTypeArguments[i])
|
||||
.getGenericComponentType();
|
||||
if (componentType instanceof Class<?>) {
|
||||
actualClasses[i] = Array.newInstance((Class<?>) componentType, 0)
|
||||
.getClass();
|
||||
} else {
|
||||
actualClasses = null;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
actualClasses = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (genType instanceof GenericArrayType) {
|
||||
Type componentType = ((GenericArrayType) genType).getGenericComponentType();
|
||||
if (componentType instanceof Class<?>) {
|
||||
actualClasses = new Class<?>[] { (Class<?>) componentType };
|
||||
}
|
||||
} else if (genType instanceof Class<?>) {// XXX this check is only
|
||||
// required for IcedTea6
|
||||
Class<?> classType = (Class<?>) genType;
|
||||
if (classType.isArray()) {
|
||||
actualClasses = new Class<?>[1];
|
||||
actualClasses[0] = getType().getComponentType();
|
||||
}
|
||||
}
|
||||
actualClassesChecked = true;
|
||||
}
|
||||
return actualClasses;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.introspector;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.List;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.YAMLException;
|
||||
import io.jenkins.plugins.casc.snakeyaml.util.ArrayUtils;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A <code>MethodProperty</code> is a <code>Property</code> which is accessed
|
||||
* through accessor methods (setX, getX). It is possible to have a
|
||||
* <code>MethodProperty</code> which has only setter, only getter, or both. It
|
||||
* is not possible to have a <code>MethodProperty</code> which has neither
|
||||
* setter nor getter.
|
||||
* </p>
|
||||
*/
|
||||
public class MethodProperty extends GenericProperty {
|
||||
|
||||
private final PropertyDescriptor property;
|
||||
private final boolean readable;
|
||||
private final boolean writable;
|
||||
|
||||
private static Type discoverGenericType(PropertyDescriptor property) {
|
||||
Method readMethod = property.getReadMethod();
|
||||
if (readMethod != null) {
|
||||
return readMethod.getGenericReturnType();
|
||||
}
|
||||
|
||||
Method writeMethod = property.getWriteMethod();
|
||||
if (writeMethod != null) {
|
||||
Type[] paramTypes = writeMethod.getGenericParameterTypes();
|
||||
if (paramTypes.length > 0) {
|
||||
return paramTypes[0];
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This actually may happen if PropertyDescriptor is of type
|
||||
* IndexedPropertyDescriptor and it has only IndexedGetter/Setter. ATM
|
||||
* we simply skip type discovery.
|
||||
*/
|
||||
return null;
|
||||
}
|
||||
|
||||
public MethodProperty(PropertyDescriptor property) {
|
||||
super(property.getName(), property.getPropertyType(),
|
||||
MethodProperty.discoverGenericType(property));
|
||||
this.property = property;
|
||||
this.readable = property.getReadMethod() != null;
|
||||
this.writable = property.getWriteMethod() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(Object object, Object value) throws Exception {
|
||||
if (!writable) {
|
||||
throw new YAMLException("No writable property '" + getName() + "' on class: "
|
||||
+ object.getClass().getName());
|
||||
}
|
||||
property.getWriteMethod().invoke(object, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(Object object) {
|
||||
try {
|
||||
property.getReadMethod().setAccessible(true);// issue 50
|
||||
return property.getReadMethod().invoke(object);
|
||||
} catch (Exception e) {
|
||||
throw new YAMLException("Unable to find getter for property '" + property.getName()
|
||||
+ "' on object " + object + ":" + e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the annotations that are present on read and write methods of this property or empty {@code List} if
|
||||
* there're no annotations.
|
||||
*
|
||||
* @return the annotations that are present on this property or empty {@code List} if there're no annotations
|
||||
*/
|
||||
@Override
|
||||
public List<Annotation> getAnnotations() {
|
||||
List<Annotation> annotations;
|
||||
if (isReadable() && isWritable()) {
|
||||
annotations = ArrayUtils.toUnmodifiableCompositeList(property.getReadMethod().getAnnotations(), property.getWriteMethod().getAnnotations());
|
||||
} else if (isReadable()) {
|
||||
annotations = ArrayUtils.toUnmodifiableList(property.getReadMethod().getAnnotations());
|
||||
} else {
|
||||
annotations = ArrayUtils.toUnmodifiableList(property.getWriteMethod().getAnnotations());
|
||||
}
|
||||
return annotations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns property's annotation for the given type or {@code null} if it's not present. If the annotation is present
|
||||
* on both read and write methods, the annotation on read method takes precedence.
|
||||
*
|
||||
* @param annotationType the type of the annotation to be returned
|
||||
* @return property's annotation for the given type or {@code null} if it's not present
|
||||
*/
|
||||
@Override
|
||||
public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
|
||||
A annotation = null;
|
||||
if (isReadable()) {
|
||||
annotation = property.getReadMethod().getAnnotation(annotationType);
|
||||
}
|
||||
if (annotation == null && isWritable()) {
|
||||
annotation = property.getWriteMethod().getAnnotation(annotationType);
|
||||
}
|
||||
return annotation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWritable() {
|
||||
return writable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadable() {
|
||||
return readable;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.introspector;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A property that does not map to a real property; this is used when {@link
|
||||
* PropertyUtils}.setSkipMissingProperties(boolean) is set to true.
|
||||
*/
|
||||
public class MissingProperty extends Property {
|
||||
|
||||
public MissingProperty(String name) {
|
||||
super(name, Object.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] getActualTypeArguments() {
|
||||
return new Class[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter does nothing.
|
||||
*/
|
||||
@Override
|
||||
public void set(Object object, Object value) throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(Object object) {
|
||||
return object;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Annotation> getAnnotations() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.introspector;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A <code>Property</code> represents a single member variable of a class,
|
||||
* possibly including its accessor methods (getX, setX). The name stored in this
|
||||
* class is the actual name of the property as given for the class, not an
|
||||
* alias.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Objects of this class have a total ordering which defaults to ordering based
|
||||
* on the name of the property.
|
||||
* </p>
|
||||
*/
|
||||
public abstract class Property implements Comparable<Property> {
|
||||
|
||||
private final String name;
|
||||
private final Class<?> type;
|
||||
|
||||
public Property(String name, Class<?> type) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Class<?> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
abstract public Class<?>[] getActualTypeArguments();
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName() + " of " + getType();
|
||||
}
|
||||
|
||||
public int compareTo(Property o) {
|
||||
return getName().compareTo(o.getName());
|
||||
}
|
||||
|
||||
public boolean isWritable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isReadable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
abstract public void set(Object object, Object value) throws Exception;
|
||||
|
||||
abstract public Object get(Object object);
|
||||
|
||||
/**
|
||||
* Returns the annotations that are present on this property or empty {@code List} if there're no annotations.
|
||||
*
|
||||
* @return the annotations that are present on this property or empty {@code List} if there're no annotations
|
||||
*/
|
||||
abstract public List<Annotation> getAnnotations();
|
||||
|
||||
/**
|
||||
* Returns property's annotation for the given type or {@code null} if it's not present.
|
||||
*
|
||||
* @param annotationType the type of the annotation to be returned
|
||||
* @param <A> class of the annotation
|
||||
*
|
||||
* @return property's annotation for the given type or {@code null} if it's not present
|
||||
*/
|
||||
abstract public <A extends Annotation> A getAnnotation(Class<A> annotationType);
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getName().hashCode() + getType().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other instanceof Property) {
|
||||
Property p = (Property) other;
|
||||
return getName().equals(p.getName()) && getType().equals(p.getType());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,258 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.introspector;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.YAMLException;
|
||||
|
||||
// TODO: decide priorities for get/set Read/Field/Delegate Write/Field/Delegate - is FIELD on the correct place ?
|
||||
public class PropertySubstitute extends Property {
|
||||
|
||||
final private static Logger log = Logger.getLogger(PropertySubstitute.class.getPackage()
|
||||
.getName());
|
||||
|
||||
protected Class<?> targetType;
|
||||
private final String readMethod;
|
||||
private final String writeMethod;
|
||||
transient private Method read;
|
||||
transient private Method write;
|
||||
private Field field;
|
||||
protected Class<?>[] parameters;
|
||||
private Property delegate;
|
||||
private boolean filler;
|
||||
|
||||
public PropertySubstitute(String name, Class<?> type, String readMethod, String writeMethod,
|
||||
Class<?>... params) {
|
||||
super(name, type);
|
||||
this.readMethod = readMethod;
|
||||
this.writeMethod = writeMethod;
|
||||
setActualTypeArguments(params);
|
||||
this.filler = false;
|
||||
}
|
||||
|
||||
public PropertySubstitute(String name, Class<?> type, Class<?>... params) {
|
||||
this(name, type, null, null, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] getActualTypeArguments() {
|
||||
if (parameters == null && delegate != null) {
|
||||
return delegate.getActualTypeArguments();
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public void setActualTypeArguments(Class<?>... args) {
|
||||
if (args != null && args.length > 0) {
|
||||
parameters = args;
|
||||
} else {
|
||||
parameters = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(Object object, Object value) throws Exception {
|
||||
if (write != null) {
|
||||
if (!filler) {
|
||||
write.invoke(object, value);
|
||||
} else if (value != null) {
|
||||
if (value instanceof Collection<?>) {
|
||||
Collection<?> collection = (Collection<?>) value;
|
||||
for (Object val : collection) {
|
||||
write.invoke(object, val);
|
||||
}
|
||||
} else if (value instanceof Map<?, ?>) {
|
||||
Map<?, ?> map = (Map<?, ?>) value;
|
||||
for (Entry<?, ?> entry : map.entrySet()) {
|
||||
write.invoke(object, entry.getKey(), entry.getValue());
|
||||
}
|
||||
} else if (value.getClass().isArray()) { // TODO: maybe arrays
|
||||
// need 2 fillers like
|
||||
// SET(index, value)
|
||||
// add ADD(value)
|
||||
int len = Array.getLength(value);
|
||||
for (int i = 0; i < len; i++) {
|
||||
write.invoke(object, Array.get(value, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (field != null) {
|
||||
field.set(object, value);
|
||||
} else if (delegate != null) {
|
||||
delegate.set(object, value);
|
||||
} else {
|
||||
log.warning("No setter/delegate for '" + getName() + "' on object " + object);
|
||||
}
|
||||
// TODO: maybe throw YAMLException here
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(Object object) {
|
||||
try {
|
||||
if (read != null) {
|
||||
return read.invoke(object);
|
||||
} else if (field != null) {
|
||||
return field.get(object);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new YAMLException("Unable to find getter for property '" + getName()
|
||||
+ "' on object " + object + ":" + e);
|
||||
}
|
||||
|
||||
if (delegate != null) {
|
||||
return delegate.get(object);
|
||||
}
|
||||
throw new YAMLException("No getter or delegate for property '" + getName() + "' on object "
|
||||
+ object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Annotation> getAnnotations() {
|
||||
Annotation[] annotations = null;
|
||||
if (read != null) {
|
||||
annotations = read.getAnnotations();
|
||||
} else if (field != null) {
|
||||
annotations = field.getAnnotations();
|
||||
}
|
||||
return annotations != null ? Arrays.asList(annotations) : delegate.getAnnotations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
|
||||
A annotation;
|
||||
if (read != null) {
|
||||
annotation = read.getAnnotation(annotationType);
|
||||
} else if (field != null) {
|
||||
annotation = field.getAnnotation(annotationType);
|
||||
} else {
|
||||
annotation = delegate.getAnnotation(annotationType);
|
||||
}
|
||||
return annotation;
|
||||
}
|
||||
|
||||
public void setTargetType(Class<?> targetType) {
|
||||
if (this.targetType != targetType) {
|
||||
this.targetType = targetType;
|
||||
|
||||
final String name = getName();
|
||||
for (Class<?> c = targetType; c != null; c = c.getSuperclass()) {
|
||||
for (Field f : c.getDeclaredFields()) {
|
||||
if (f.getName().equals(name)) {
|
||||
int modifiers = f.getModifiers();
|
||||
if (!Modifier.isStatic(modifiers) && !Modifier.isTransient(modifiers)) {
|
||||
f.setAccessible(true);
|
||||
field = f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (field == null && log.isLoggable(Level.FINE)) {
|
||||
log.fine(String.format("Failed to find field for %s.%s", targetType.getName(),
|
||||
getName()));
|
||||
}
|
||||
|
||||
// Retrieve needed info
|
||||
if (readMethod != null) {
|
||||
read = discoverMethod(targetType, readMethod);
|
||||
}
|
||||
if (writeMethod != null) {
|
||||
filler = false;
|
||||
write = discoverMethod(targetType, writeMethod, getType());
|
||||
if (write == null && parameters != null) {
|
||||
filler = true;
|
||||
write = discoverMethod(targetType, writeMethod, parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Method discoverMethod(Class<?> type, String name, Class<?>... params) {
|
||||
for (Class<?> c = type; c != null; c = c.getSuperclass()) {
|
||||
for (Method method : c.getDeclaredMethods()) {
|
||||
if (name.equals(method.getName())) {
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
if (parameterTypes.length != params.length) {
|
||||
continue;
|
||||
}
|
||||
boolean found = true;
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
if (!parameterTypes[i].isAssignableFrom(params[i])) {
|
||||
found = false;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
method.setAccessible(true);
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (log.isLoggable(Level.FINE)) {
|
||||
log.fine(String.format("Failed to find [%s(%d args)] for %s.%s", name, params.length,
|
||||
targetType.getName(), getName()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
final String n = super.getName();
|
||||
if (n != null) {
|
||||
return n;
|
||||
}
|
||||
return delegate != null ? delegate.getName() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getType() {
|
||||
final Class<?> t = super.getType();
|
||||
if (t != null) {
|
||||
return t;
|
||||
}
|
||||
return delegate != null ? delegate.getType() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadable() {
|
||||
return (read != null) || (field != null) || (delegate != null && delegate.isReadable());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWritable() {
|
||||
return (write != null) || (field != null) || (delegate != null && delegate.isWritable());
|
||||
}
|
||||
|
||||
public void setDelegate(Property delegate) {
|
||||
this.delegate = delegate;
|
||||
if (writeMethod != null && write == null && !filler) {
|
||||
filler = true;
|
||||
write = discoverMethod(targetType, writeMethod, getActualTypeArguments());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,205 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.introspector;
|
||||
|
||||
import java.beans.FeatureDescriptor;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.YAMLException;
|
||||
import io.jenkins.plugins.casc.snakeyaml.util.PlatformFeatureDetector;
|
||||
|
||||
public class PropertyUtils {
|
||||
|
||||
private final Map<Class<?>, Map<String, Property>> propertiesCache = new HashMap<Class<?>, Map<String, Property>>();
|
||||
private final Map<Class<?>, Set<Property>> readableProperties = new HashMap<Class<?>, Set<Property>>();
|
||||
private BeanAccess beanAccess = BeanAccess.DEFAULT;
|
||||
private boolean allowReadOnlyProperties = false;
|
||||
private boolean skipMissingProperties = false;
|
||||
|
||||
private PlatformFeatureDetector platformFeatureDetector;
|
||||
|
||||
public PropertyUtils() {
|
||||
this(new PlatformFeatureDetector());
|
||||
}
|
||||
|
||||
PropertyUtils(PlatformFeatureDetector platformFeatureDetector) {
|
||||
this.platformFeatureDetector = platformFeatureDetector;
|
||||
|
||||
/*
|
||||
* Android lacks much of java.beans (including the Introspector class, used here), because java.beans classes tend to rely on java.awt, which isn't
|
||||
* supported in the Android SDK. That means we have to fall back on FIELD access only when SnakeYAML is running on the Android Runtime.
|
||||
*/
|
||||
if (platformFeatureDetector.isRunningOnAndroid()) {
|
||||
beanAccess = BeanAccess.FIELD;
|
||||
}
|
||||
}
|
||||
|
||||
protected Map<String, Property> getPropertiesMap(Class<?> type, BeanAccess bAccess) {
|
||||
if (propertiesCache.containsKey(type)) {
|
||||
return propertiesCache.get(type);
|
||||
}
|
||||
|
||||
Map<String, Property> properties = new LinkedHashMap<String, Property>();
|
||||
boolean inaccessableFieldsExist = false;
|
||||
switch (bAccess) {
|
||||
case FIELD:
|
||||
for (Class<?> c = type; c != null; c = c.getSuperclass()) {
|
||||
for (Field field : c.getDeclaredFields()) {
|
||||
int modifiers = field.getModifiers();
|
||||
if (!Modifier.isStatic(modifiers) && !Modifier.isTransient(modifiers)
|
||||
&& !properties.containsKey(field.getName())) {
|
||||
properties.put(field.getName(), new FieldProperty(field));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// add JavaBean properties
|
||||
try {
|
||||
for (PropertyDescriptor property : Introspector.getBeanInfo(type)
|
||||
.getPropertyDescriptors()) {
|
||||
Method readMethod = property.getReadMethod();
|
||||
if ((readMethod == null || !readMethod.getName().equals("getClass"))
|
||||
&& !isTransient(property)) {
|
||||
properties.put(property.getName(), new MethodProperty(property));
|
||||
}
|
||||
}
|
||||
} catch (IntrospectionException e) {
|
||||
throw new YAMLException(e);
|
||||
}
|
||||
|
||||
// add public fields
|
||||
for (Class<?> c = type; c != null; c = c.getSuperclass()) {
|
||||
for (Field field : c.getDeclaredFields()) {
|
||||
int modifiers = field.getModifiers();
|
||||
if (!Modifier.isStatic(modifiers) && !Modifier.isTransient(modifiers)) {
|
||||
if (Modifier.isPublic(modifiers)) {
|
||||
properties.put(field.getName(), new FieldProperty(field));
|
||||
} else {
|
||||
inaccessableFieldsExist = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (properties.isEmpty() && inaccessableFieldsExist) {
|
||||
throw new YAMLException("No JavaBean properties found in " + type.getName());
|
||||
}
|
||||
propertiesCache.put(type, properties);
|
||||
return properties;
|
||||
}
|
||||
|
||||
private static final String TRANSIENT = "transient";
|
||||
|
||||
private boolean isTransient(FeatureDescriptor fd) {
|
||||
return Boolean.TRUE.equals(fd.getValue(TRANSIENT));
|
||||
}
|
||||
|
||||
public Set<Property> getProperties(Class<? extends Object> type) {
|
||||
return getProperties(type, beanAccess);
|
||||
}
|
||||
|
||||
public Set<Property> getProperties(Class<? extends Object> type, BeanAccess bAccess) {
|
||||
if (readableProperties.containsKey(type)) {
|
||||
return readableProperties.get(type);
|
||||
}
|
||||
Set<Property> properties = createPropertySet(type, bAccess);
|
||||
readableProperties.put(type, properties);
|
||||
return properties;
|
||||
}
|
||||
|
||||
protected Set<Property> createPropertySet(Class<? extends Object> type, BeanAccess bAccess) {
|
||||
Set<Property> properties = new TreeSet<Property>();
|
||||
Collection<Property> props = getPropertiesMap(type, bAccess).values();
|
||||
for (Property property : props) {
|
||||
if (property.isReadable() && (allowReadOnlyProperties || property.isWritable())) {
|
||||
properties.add(property);
|
||||
}
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
public Property getProperty(Class<? extends Object> type, String name) {
|
||||
return getProperty(type, name, beanAccess);
|
||||
}
|
||||
|
||||
public Property getProperty(Class<? extends Object> type, String name, BeanAccess bAccess) {
|
||||
Map<String, Property> properties = getPropertiesMap(type, bAccess);
|
||||
Property property = properties.get(name);
|
||||
if (property == null && skipMissingProperties) {
|
||||
property = new MissingProperty(name);
|
||||
}
|
||||
if (property == null) {
|
||||
throw new YAMLException(
|
||||
"Unable to find property '" + name + "' on class: " + type.getName());
|
||||
}
|
||||
return property;
|
||||
}
|
||||
|
||||
public void setBeanAccess(BeanAccess beanAccess) {
|
||||
if (platformFeatureDetector.isRunningOnAndroid() && beanAccess != BeanAccess.FIELD) {
|
||||
throw new IllegalArgumentException(
|
||||
"JVM is Android - only BeanAccess.FIELD is available");
|
||||
}
|
||||
|
||||
if (this.beanAccess != beanAccess) {
|
||||
this.beanAccess = beanAccess;
|
||||
propertiesCache.clear();
|
||||
readableProperties.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void setAllowReadOnlyProperties(boolean allowReadOnlyProperties) {
|
||||
if (this.allowReadOnlyProperties != allowReadOnlyProperties) {
|
||||
this.allowReadOnlyProperties = allowReadOnlyProperties;
|
||||
readableProperties.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAllowReadOnlyProperties() {
|
||||
return allowReadOnlyProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip properties that are missing during deserialization of YAML to a Java
|
||||
* object. The default is false.
|
||||
*
|
||||
* @param skipMissingProperties
|
||||
* true if missing properties should be skipped, false otherwise.
|
||||
*/
|
||||
public void setSkipMissingProperties(boolean skipMissingProperties) {
|
||||
if (this.skipMissingProperties != skipMissingProperties) {
|
||||
this.skipMissingProperties = skipMissingProperties;
|
||||
readableProperties.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSkipMissingProperties() {
|
||||
return skipMissingProperties;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.nodes;
|
||||
|
||||
public class AnchorNode extends Node {
|
||||
|
||||
private Node realNode;
|
||||
|
||||
public AnchorNode(Node realNode) {
|
||||
super(realNode.getTag(), realNode.getStartMark(), realNode.getEndMark());
|
||||
this.realNode = realNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeId getNodeId() {
|
||||
return NodeId.anchor;
|
||||
}
|
||||
|
||||
public Node getRealNode() {
|
||||
return realNode;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.nodes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.DumperOptions;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
/**
|
||||
* Base class for the two collection types {@link MappingNode mapping} and
|
||||
* {@link SequenceNode collection}.
|
||||
*/
|
||||
public abstract class CollectionNode<T> extends Node {
|
||||
private DumperOptions.FlowStyle flowStyle;
|
||||
|
||||
public CollectionNode(Tag tag, Mark startMark, Mark endMark, DumperOptions.FlowStyle flowStyle) {
|
||||
super(tag, startMark, endMark);
|
||||
setFlowStyle(flowStyle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Existed in older versions but replaced with {@link DumperOptions.FlowStyle}-based constructor.
|
||||
* Restored in v1.22 for backwards compatibility.
|
||||
* @deprecated Since restored in v1.22. Use {@link CollectionNode#CollectionNode(Tag, Mark, Mark, io.jenkins.plugins.casc.snakeyaml.DumperOptions.FlowStyle) }.
|
||||
*/
|
||||
@Deprecated
|
||||
public CollectionNode(Tag tag, Mark startMark, Mark endMark, Boolean flowStyle) {
|
||||
this(tag, startMark, endMark, DumperOptions.FlowStyle.fromBoolean(flowStyle));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the elements in this sequence.
|
||||
*
|
||||
* @return Nodes in the specified order.
|
||||
*/
|
||||
abstract public List<T> getValue();
|
||||
|
||||
/**
|
||||
* Serialization style of this collection.
|
||||
*
|
||||
* @return <code>true</code> for flow style, <code>false</code> for block
|
||||
* style.
|
||||
*/
|
||||
public DumperOptions.FlowStyle getFlowStyle() {
|
||||
return flowStyle;
|
||||
}
|
||||
|
||||
public void setFlowStyle(DumperOptions.FlowStyle flowStyle) {
|
||||
if (flowStyle == null) throw new NullPointerException("Flow style must be provided.");
|
||||
this.flowStyle = flowStyle;
|
||||
}
|
||||
|
||||
public void setEndMark(Mark endMark) {
|
||||
this.endMark = endMark;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.nodes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.DumperOptions;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
/**
|
||||
* Represents a map.
|
||||
* <p>
|
||||
* A map is a collection of unsorted key-value pairs.
|
||||
* </p>
|
||||
*/
|
||||
public class MappingNode extends CollectionNode<NodeTuple> {
|
||||
private List<NodeTuple> value;
|
||||
private boolean merged = false;
|
||||
|
||||
public MappingNode(Tag tag, boolean resolved, List<NodeTuple> value, Mark startMark,
|
||||
Mark endMark, DumperOptions.FlowStyle flowStyle) {
|
||||
super(tag, startMark, endMark, flowStyle);
|
||||
if (value == null) {
|
||||
throw new NullPointerException("value in a Node is required.");
|
||||
}
|
||||
this.value = value;
|
||||
this.resolved = resolved;
|
||||
}
|
||||
|
||||
public MappingNode(Tag tag, List<NodeTuple> value, DumperOptions.FlowStyle flowStyle) {
|
||||
this(tag, true, value, null, null, flowStyle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Existed in older versions but replaced with {@link DumperOptions.FlowStyle}-based constructor.
|
||||
* Restored in v1.22 for backwards compatibility.
|
||||
* @deprecated Since restored in v1.22. Use {@link MappingNode#MappingNode(Tag, boolean, List, Mark, Mark, io.jenkins.plugins.casc.snakeyaml.DumperOptions.FlowStyle) }.
|
||||
*/
|
||||
@Deprecated
|
||||
public MappingNode(Tag tag, boolean resolved, List<NodeTuple> value, Mark startMark,
|
||||
Mark endMark, Boolean flowStyle) {
|
||||
this(tag, resolved, value, startMark, endMark, DumperOptions.FlowStyle.fromBoolean(flowStyle));
|
||||
}
|
||||
|
||||
/*
|
||||
* Existed in older versions but replaced with {@link DumperOptions.FlowStyle}-based constructor.
|
||||
* Restored in v1.22 for backwards compatibility.
|
||||
* @deprecated Since restored in v1.22. Use {@link MappingNode#MappingNode(Tag, List, io.jenkins.plugins.casc.snakeyaml.DumperOptions.FlowStyle) }.
|
||||
*/
|
||||
@Deprecated
|
||||
public MappingNode(Tag tag, List<NodeTuple> value, Boolean flowStyle) {
|
||||
this(tag, value, DumperOptions.FlowStyle.fromBoolean(flowStyle));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeId getNodeId() {
|
||||
return NodeId.mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entries of this map.
|
||||
*
|
||||
* @return List of entries.
|
||||
*/
|
||||
public List<NodeTuple> getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(List<NodeTuple> mergedValue) {
|
||||
value = mergedValue;
|
||||
}
|
||||
|
||||
public void setOnlyKeyType(Class<? extends Object> keyType) {
|
||||
for (NodeTuple nodes : value) {
|
||||
nodes.getKeyNode().setType(keyType);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTypes(Class<? extends Object> keyType, Class<? extends Object> valueType) {
|
||||
for (NodeTuple nodes : value) {
|
||||
nodes.getValueNode().setType(valueType);
|
||||
nodes.getKeyNode().setType(keyType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String values;
|
||||
StringBuilder buf = new StringBuilder();
|
||||
for (NodeTuple node : getValue()) {
|
||||
buf.append("{ key=");
|
||||
buf.append(node.getKeyNode());
|
||||
buf.append("; value=");
|
||||
if (node.getValueNode() instanceof CollectionNode) {
|
||||
// to avoid overflow in case of recursive structures
|
||||
buf.append(System.identityHashCode(node.getValueNode()));
|
||||
} else {
|
||||
buf.append(node.toString());
|
||||
}
|
||||
buf.append(" }");
|
||||
}
|
||||
values = buf.toString();
|
||||
return "<" + this.getClass().getName() + " (tag=" + getTag() + ", values=" + values + ")>";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param merged
|
||||
* - true if map contains merge node
|
||||
*/
|
||||
public void setMerged(boolean merged) {
|
||||
this.merged = merged;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if map contains merge node
|
||||
*/
|
||||
public boolean isMerged() {
|
||||
return merged;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.nodes;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
/**
|
||||
* Base class for all nodes.
|
||||
* <p>
|
||||
* The nodes form the node-graph described in the <a
|
||||
* href="http://yaml.org/spec/1.1/">YAML Specification</a>.
|
||||
* </p>
|
||||
* <p>
|
||||
* While loading, the node graph is usually created by the
|
||||
* {@link io.jenkins.plugins.casc.snakeyaml.composer.Composer}, and later transformed into
|
||||
* application specific Java classes by the classes from the
|
||||
* {@link io.jenkins.plugins.casc.snakeyaml.constructor} package.
|
||||
* </p>
|
||||
*/
|
||||
public abstract class Node {
|
||||
private Tag tag;
|
||||
private Mark startMark;
|
||||
protected Mark endMark;
|
||||
private Class<? extends Object> type;
|
||||
private boolean twoStepsConstruction;
|
||||
|
||||
/**
|
||||
* true when the tag is assigned by the resolver
|
||||
*/
|
||||
protected boolean resolved;
|
||||
protected Boolean useClassConstructor;
|
||||
|
||||
public Node(Tag tag, Mark startMark, Mark endMark) {
|
||||
setTag(tag);
|
||||
this.startMark = startMark;
|
||||
this.endMark = endMark;
|
||||
this.type = Object.class;
|
||||
this.twoStepsConstruction = false;
|
||||
this.resolved = true;
|
||||
this.useClassConstructor = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag of this node.
|
||||
* <p>
|
||||
* Every node has a tag assigned. The tag is either local or global.
|
||||
*
|
||||
* @return Tag of this node.
|
||||
*/
|
||||
public Tag getTag() {
|
||||
return this.tag;
|
||||
}
|
||||
|
||||
public Mark getEndMark() {
|
||||
return endMark;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return scalar, sequence, mapping
|
||||
*/
|
||||
public abstract NodeId getNodeId();
|
||||
|
||||
public Mark getStartMark() {
|
||||
return startMark;
|
||||
}
|
||||
|
||||
public void setTag(Tag tag) {
|
||||
if (tag == null) {
|
||||
throw new NullPointerException("tag in a Node is required.");
|
||||
}
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Node is only equal to itself
|
||||
*/
|
||||
@Override
|
||||
public final boolean equals(Object obj) {
|
||||
return super.equals(obj);
|
||||
}
|
||||
|
||||
public Class<? extends Object> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(Class<? extends Object> type) {
|
||||
if (!type.isAssignableFrom(this.type)) {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
public void setTwoStepsConstruction(boolean twoStepsConstruction) {
|
||||
this.twoStepsConstruction = twoStepsConstruction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this node must be constructed in two steps.
|
||||
* <p>
|
||||
* Two-step construction is required whenever a node is a child (direct or
|
||||
* indirect) of it self. That is, if a recursive structure is build using
|
||||
* anchors and aliases.
|
||||
* </p>
|
||||
* <p>
|
||||
* Set by {@link io.jenkins.plugins.casc.snakeyaml.composer.Composer}, used during the
|
||||
* construction process.
|
||||
* </p>
|
||||
* <p>
|
||||
* Only relevant during loading.
|
||||
* </p>
|
||||
*
|
||||
* @return <code>true</code> if the node is self referenced.
|
||||
*/
|
||||
public boolean isTwoStepsConstruction() {
|
||||
return twoStepsConstruction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
public boolean useClassConstructor() {
|
||||
if (useClassConstructor == null) {
|
||||
if (!tag.isSecondary() && resolved && !Object.class.equals(type)
|
||||
&& !tag.equals(Tag.NULL)) {
|
||||
return true;
|
||||
} else if (tag.isCompatible(getType())) {
|
||||
// the tag is compatible with the runtime class
|
||||
// the tag will be ignored
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return useClassConstructor.booleanValue();
|
||||
}
|
||||
|
||||
public void setUseClassConstructor(Boolean useClassConstructor) {
|
||||
this.useClassConstructor = useClassConstructor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the tag was added by
|
||||
* {@link io.jenkins.plugins.casc.snakeyaml.resolver.Resolver}.
|
||||
*
|
||||
* @return true if the tag of this node was resolved
|
||||
*
|
||||
* @deprecated Since v1.22. Absent in immediately prior versions, but present previously. Restored deprecated for backwards compatibility.
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isResolved() {
|
||||
return resolved;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.nodes;
|
||||
|
||||
/**
|
||||
* Enum for the basic YAML types: scalar, sequence, mapping or anchor.
|
||||
*/
|
||||
public enum NodeId {
|
||||
scalar, sequence, mapping, anchor
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.nodes;
|
||||
|
||||
/**
|
||||
* Stores one key value pair used in a map.
|
||||
*/
|
||||
public final class NodeTuple {
|
||||
|
||||
private Node keyNode;
|
||||
private Node valueNode;
|
||||
|
||||
public NodeTuple(Node keyNode, Node valueNode) {
|
||||
if (keyNode == null || valueNode == null) {
|
||||
throw new NullPointerException("Nodes must be provided.");
|
||||
}
|
||||
this.keyNode = keyNode;
|
||||
this.valueNode = valueNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Key node.
|
||||
*
|
||||
* @return the node used as key
|
||||
*/
|
||||
public Node getKeyNode() {
|
||||
return keyNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Value node.
|
||||
*
|
||||
* @return node used as value
|
||||
*/
|
||||
public Node getValueNode() {
|
||||
return valueNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "<NodeTuple keyNode=" + keyNode.toString() + "; valueNode=" + valueNode.toString()
|
||||
+ ">";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.nodes;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.DumperOptions;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
/**
|
||||
* Represents a scalar node.
|
||||
* <p>
|
||||
* Scalar nodes form the leaves in the node graph.
|
||||
* </p>
|
||||
*/
|
||||
public class ScalarNode extends Node {
|
||||
private DumperOptions.ScalarStyle style;
|
||||
private String value;
|
||||
|
||||
public ScalarNode(Tag tag, String value, Mark startMark, Mark endMark, DumperOptions.ScalarStyle style) {
|
||||
this(tag, true, value, startMark, endMark, style);
|
||||
}
|
||||
|
||||
public ScalarNode(Tag tag, boolean resolved, String value, Mark startMark, Mark endMark,
|
||||
DumperOptions.ScalarStyle style) {
|
||||
super(tag, startMark, endMark);
|
||||
if (value == null) {
|
||||
throw new NullPointerException("value in a Node is required.");
|
||||
}
|
||||
this.value = value;
|
||||
if (style == null) throw new NullPointerException("Scalar style must be provided.");
|
||||
this.style = style;
|
||||
this.resolved = resolved;
|
||||
}
|
||||
|
||||
/*
|
||||
* Existed in older versions but replaced with {@link DumperOptions.ScalarStyle}-based constructor.
|
||||
* Restored in v1.22 for backwards compatibility.
|
||||
* @deprecated Since restored in v1.22. Use {@link ScalarNode#ScalarNode(Tag, String, Mark, Mark, io.jenkins.plugins.casc.snakeyaml.DumperOptions.ScalarStyle) }.
|
||||
*/
|
||||
@Deprecated
|
||||
public ScalarNode(Tag tag, String value, Mark startMark, Mark endMark, Character style) {
|
||||
this(tag, value, startMark, endMark, DumperOptions.ScalarStyle.createStyle(style));
|
||||
}
|
||||
|
||||
/*
|
||||
* Existed in older versions but replaced with {@link DumperOptions.ScalarStyle}-based constructor.
|
||||
* Restored in v1.22 for backwards compatibility.
|
||||
* @deprecated Since restored in v1.22. Use {@link ScalarNode#ScalarNode(Tag, boolean, String, Mark, Mark, io.jenkins.plugins.casc.snakeyaml.DumperOptions.ScalarStyle) }.
|
||||
*/
|
||||
@Deprecated
|
||||
public ScalarNode(Tag tag, boolean resolved, String value, Mark startMark, Mark endMark,
|
||||
Character style) {
|
||||
this(tag, resolved, value, startMark, endMark, DumperOptions.ScalarStyle.createStyle(style));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get scalar style of this node.
|
||||
*
|
||||
* @see io.jenkins.plugins.casc.snakeyaml.events.ScalarEvent
|
||||
* @see <a href="http://yaml.org/spec/1.1/#id903915">Chapter 9. Scalar
|
||||
* Styles</a>
|
||||
* @return style of this scalar node
|
||||
* @deprecated use getScalarStyle instead
|
||||
*/
|
||||
@Deprecated
|
||||
public Character getStyle() {
|
||||
return style.getChar();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get scalar style of this node.
|
||||
*
|
||||
* @see io.jenkins.plugins.casc.snakeyaml.events.ScalarEvent
|
||||
* @see <a href="http://yaml.org/spec/1.1/#id903915">Chapter 9. Scalar
|
||||
* Styles</a>
|
||||
* @return style of this scalar node
|
||||
*/
|
||||
public DumperOptions.ScalarStyle getScalarStyle() {
|
||||
return style;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeId getNodeId() {
|
||||
return NodeId.scalar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Value of this scalar.
|
||||
*
|
||||
* @return Scalar's value.
|
||||
*/
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "<" + this.getClass().getName() + " (tag=" + getTag() + ", value=" + getValue()
|
||||
+ ")>";
|
||||
}
|
||||
|
||||
public boolean isPlain() {
|
||||
return style == DumperOptions.ScalarStyle.PLAIN;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.nodes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.DumperOptions;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
/**
|
||||
* Represents a sequence.
|
||||
* <p>
|
||||
* A sequence is a ordered collection of nodes.
|
||||
* </p>
|
||||
*/
|
||||
public class SequenceNode extends CollectionNode<Node> {
|
||||
final private List<Node> value;
|
||||
|
||||
public SequenceNode(Tag tag, boolean resolved, List<Node> value, Mark startMark, Mark endMark,
|
||||
DumperOptions.FlowStyle flowStyle) {
|
||||
super(tag, startMark, endMark, flowStyle);
|
||||
if (value == null) {
|
||||
throw new NullPointerException("value in a Node is required.");
|
||||
}
|
||||
this.value = value;
|
||||
this.resolved = resolved;
|
||||
}
|
||||
|
||||
public SequenceNode(Tag tag, List<Node> value, DumperOptions.FlowStyle flowStyle) {
|
||||
this(tag, true, value, null, null, flowStyle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Existed in older versions but replaced with {@link DumperOptions.SequenceStyle}-based constructor.
|
||||
* Restored in v1.22 for backwards compatibility.
|
||||
* @deprecated Since restored in v1.22. Use {@link SequenceNode#SequenceNode(Tag, List<Node>, io.jenkins.plugins.casc.snakeyaml.DumperOptions.FlowStyle) }.
|
||||
*/
|
||||
@Deprecated
|
||||
public SequenceNode(Tag tag, List<Node> value, Boolean style) {
|
||||
this(tag, value, DumperOptions.FlowStyle.fromBoolean(style));
|
||||
}
|
||||
|
||||
/*
|
||||
* Existed in older versions but replaced with {@link DumperOptions.SequenceStyle}-based constructor.
|
||||
* Restored in v1.22 for backwards compatibility.
|
||||
* @deprecated Since restored in v1.22. Use {@link SequenceNode#SequenceNode(Tag, boolean, List<Node>, Mark, Mark, io.jenkins.plugins.casc.snakeyaml.DumperOptions.FlowStyle) }.
|
||||
*/
|
||||
@Deprecated
|
||||
public SequenceNode(Tag tag, boolean resolved, List<Node> value, Mark startMark, Mark endMark,
|
||||
Boolean style) {
|
||||
this(tag, resolved, value, startMark, endMark, DumperOptions.FlowStyle.fromBoolean(style));
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeId getNodeId() {
|
||||
return NodeId.sequence;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the elements in this sequence.
|
||||
*
|
||||
* @return Nodes in the specified order.
|
||||
*/
|
||||
public List<Node> getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setListType(Class<? extends Object> listType) {
|
||||
for (Node node : value) {
|
||||
node.setType(listType);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "<" + this.getClass().getName() + " (tag=" + getTag() + ", value=" + getValue()
|
||||
+ ")>";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.nodes;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URI;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.YAMLException;
|
||||
import io.jenkins.plugins.casc.snakeyaml.util.UriEncoder;
|
||||
|
||||
public final class Tag {
|
||||
public static final String PREFIX = "tag:yaml.org,2002:";
|
||||
public static final Tag YAML = new Tag(PREFIX + "yaml");
|
||||
public static final Tag MERGE = new Tag(PREFIX + "merge");
|
||||
public static final Tag SET = new Tag(PREFIX + "set");
|
||||
public static final Tag PAIRS = new Tag(PREFIX + "pairs");
|
||||
public static final Tag OMAP = new Tag(PREFIX + "omap");
|
||||
public static final Tag BINARY = new Tag(PREFIX + "binary");
|
||||
public static final Tag INT = new Tag(PREFIX + "int");
|
||||
public static final Tag FLOAT = new Tag(PREFIX + "float");
|
||||
public static final Tag TIMESTAMP = new Tag(PREFIX + "timestamp");
|
||||
public static final Tag BOOL = new Tag(PREFIX + "bool");
|
||||
public static final Tag NULL = new Tag(PREFIX + "null");
|
||||
public static final Tag STR = new Tag(PREFIX + "str");
|
||||
public static final Tag SEQ = new Tag(PREFIX + "seq");
|
||||
public static final Tag MAP = new Tag(PREFIX + "map");
|
||||
public static final Map<Tag, Set<Class<?>>> COMPATIBILITY_MAP;
|
||||
static {
|
||||
COMPATIBILITY_MAP = new HashMap<Tag, Set<Class<?>>>();
|
||||
Set<Class<?>> floatSet = new HashSet<Class<?>>();
|
||||
floatSet.add(Double.class);
|
||||
floatSet.add(Float.class);
|
||||
floatSet.add(BigDecimal.class);
|
||||
COMPATIBILITY_MAP.put(FLOAT, floatSet);
|
||||
//
|
||||
Set<Class<?>> intSet = new HashSet<Class<?>>();
|
||||
intSet.add(Integer.class);
|
||||
intSet.add(Long.class);
|
||||
intSet.add(BigInteger.class);
|
||||
COMPATIBILITY_MAP.put(INT, intSet);
|
||||
//
|
||||
Set<Class<?>> timestampSet = new HashSet<Class<?>>();
|
||||
timestampSet.add(Date.class);
|
||||
timestampSet.add(java.sql.Date.class);
|
||||
timestampSet.add(Timestamp.class);
|
||||
COMPATIBILITY_MAP.put(TIMESTAMP, timestampSet);
|
||||
}
|
||||
|
||||
private final String value;
|
||||
private boolean secondary = false; // see http://www.yaml.org/refcard.html
|
||||
|
||||
public Tag(String tag) {
|
||||
if (tag == null) {
|
||||
throw new NullPointerException("Tag must be provided.");
|
||||
} else if (tag.length() == 0) {
|
||||
throw new IllegalArgumentException("Tag must not be empty.");
|
||||
} else if (tag.trim().length() != tag.length()) {
|
||||
throw new IllegalArgumentException("Tag must not contain leading or trailing spaces.");
|
||||
}
|
||||
this.value = UriEncoder.encode(tag);
|
||||
this.secondary = !tag.startsWith(PREFIX);
|
||||
}
|
||||
|
||||
public Tag(Class<? extends Object> clazz) {
|
||||
if (clazz == null) {
|
||||
throw new NullPointerException("Class for tag must be provided.");
|
||||
}
|
||||
this.value = Tag.PREFIX + UriEncoder.encode(clazz.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated - it will be removed
|
||||
* @param uri - URI to be encoded as tag value
|
||||
*/
|
||||
public Tag(URI uri) {
|
||||
if (uri == null) {
|
||||
throw new NullPointerException("URI for tag must be provided.");
|
||||
}
|
||||
this.value = uri.toASCIIString();
|
||||
}
|
||||
|
||||
public boolean isSecondary() {
|
||||
return secondary;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean startsWith(String prefix) {
|
||||
return value.startsWith(prefix);
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
if (!value.startsWith(Tag.PREFIX)) {
|
||||
throw new YAMLException("Invalid tag: " + value);
|
||||
}
|
||||
return UriEncoder.decode(value.substring(Tag.PREFIX.length()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof Tag) {
|
||||
return value.equals(((Tag) obj).getValue());
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return value.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Java has more then 1 class compatible with a language-independent tag
|
||||
* (!!int, !!float, !!timestamp etc)
|
||||
*
|
||||
* @param clazz
|
||||
* - Class to check compatibility
|
||||
* @return true when the Class can be represented by this
|
||||
* language-independent tag
|
||||
*/
|
||||
public boolean isCompatible(Class<?> clazz) {
|
||||
Set<Class<?>> set = COMPATIBILITY_MAP.get(this);
|
||||
if (set != null) {
|
||||
return set.contains(clazz);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this tag matches the global tag for the Class
|
||||
*
|
||||
* @param clazz
|
||||
* - Class to check
|
||||
* @return true when the this tag can be used as a global tag for the Class
|
||||
*/
|
||||
public boolean matches(Class<? extends Object> clazz) {
|
||||
return value.equals(Tag.PREFIX + clazz.getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.parser;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.Event;
|
||||
|
||||
/**
|
||||
* This interface represents an input stream of {@link Event Events}.
|
||||
* <p>
|
||||
* The parser and the scanner form together the 'Parse' step in the loading
|
||||
* process (see chapter 3.1 of the <a href="http://yaml.org/spec/1.1/">YAML
|
||||
* Specification</a>).
|
||||
* </p>
|
||||
*
|
||||
* @see io.jenkins.plugins.casc.snakeyaml.events.Event
|
||||
*/
|
||||
public interface Parser {
|
||||
|
||||
/**
|
||||
* Check if the next event is one of the given type.
|
||||
*
|
||||
* @param choice
|
||||
* Event ID.
|
||||
* @return <code>true</code> if the next event can be assigned to a variable
|
||||
* of the given type. Returns <code>false</code> if no more events
|
||||
* are available.
|
||||
* @throws ParserException
|
||||
* Thrown in case of malformed input.
|
||||
*/
|
||||
public boolean checkEvent(Event.ID choice);
|
||||
|
||||
/**
|
||||
* Return the next event, but do not delete it from the stream.
|
||||
*
|
||||
* @return The event that will be returned on the next call to
|
||||
* {@link #getEvent}
|
||||
* @throws ParserException
|
||||
* Thrown in case of malformed input.
|
||||
*/
|
||||
public Event peekEvent();
|
||||
|
||||
/**
|
||||
* Returns the next event.
|
||||
* <p>
|
||||
* The event will be removed from the stream.
|
||||
* </p>
|
||||
* @return the next parsed event
|
||||
* @throws ParserException
|
||||
* Thrown in case of malformed input.
|
||||
*/
|
||||
public Event getEvent();
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.parser;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.MarkedYAMLException;
|
||||
|
||||
/**
|
||||
* Exception thrown by the {@link Parser} implementations in case of malformed
|
||||
* input.
|
||||
*/
|
||||
public class ParserException extends MarkedYAMLException {
|
||||
private static final long serialVersionUID = -2349253802798398038L;
|
||||
|
||||
/**
|
||||
* Constructs an instance.
|
||||
*
|
||||
* @param context
|
||||
* Part of the input document in which vicinity the problem
|
||||
* occurred.
|
||||
* @param contextMark
|
||||
* Position of the <code>context</code> within the document.
|
||||
* @param problem
|
||||
* Part of the input document that caused the problem.
|
||||
* @param problemMark
|
||||
* Position of the <code>problem</code>. within the document.
|
||||
*/
|
||||
public ParserException(String context, Mark contextMark, String problem, Mark problemMark) {
|
||||
super(context, contextMark, problem, problemMark, null, null);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,795 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.parser;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.DumperOptions;
|
||||
import io.jenkins.plugins.casc.snakeyaml.DumperOptions.Version;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.YAMLException;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.AliasEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.DocumentEndEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.DocumentStartEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.Event;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.ImplicitTuple;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.MappingEndEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.MappingStartEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.ScalarEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.SequenceEndEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.SequenceStartEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.StreamEndEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.StreamStartEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Tag;
|
||||
import io.jenkins.plugins.casc.snakeyaml.reader.StreamReader;
|
||||
import io.jenkins.plugins.casc.snakeyaml.scanner.Scanner;
|
||||
import io.jenkins.plugins.casc.snakeyaml.scanner.ScannerImpl;
|
||||
import io.jenkins.plugins.casc.snakeyaml.tokens.AliasToken;
|
||||
import io.jenkins.plugins.casc.snakeyaml.tokens.AnchorToken;
|
||||
import io.jenkins.plugins.casc.snakeyaml.tokens.BlockEntryToken;
|
||||
import io.jenkins.plugins.casc.snakeyaml.tokens.DirectiveToken;
|
||||
import io.jenkins.plugins.casc.snakeyaml.tokens.ScalarToken;
|
||||
import io.jenkins.plugins.casc.snakeyaml.tokens.StreamEndToken;
|
||||
import io.jenkins.plugins.casc.snakeyaml.tokens.StreamStartToken;
|
||||
import io.jenkins.plugins.casc.snakeyaml.tokens.TagToken;
|
||||
import io.jenkins.plugins.casc.snakeyaml.tokens.TagTuple;
|
||||
import io.jenkins.plugins.casc.snakeyaml.tokens.Token;
|
||||
import io.jenkins.plugins.casc.snakeyaml.util.ArrayStack;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* # The following YAML grammar is LL(1) and is parsed by a recursive descent
|
||||
* parser.
|
||||
* stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
|
||||
* implicit_document ::= block_node DOCUMENT-END*
|
||||
* explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
|
||||
* block_node_or_indentless_sequence ::=
|
||||
* ALIAS
|
||||
* | properties (block_content | indentless_block_sequence)?
|
||||
* | block_content
|
||||
* | indentless_block_sequence
|
||||
* block_node ::= ALIAS
|
||||
* | properties block_content?
|
||||
* | block_content
|
||||
* flow_node ::= ALIAS
|
||||
* | properties flow_content?
|
||||
* | flow_content
|
||||
* properties ::= TAG ANCHOR? | ANCHOR TAG?
|
||||
* block_content ::= block_collection | flow_collection | SCALAR
|
||||
* flow_content ::= flow_collection | SCALAR
|
||||
* block_collection ::= block_sequence | block_mapping
|
||||
* flow_collection ::= flow_sequence | flow_mapping
|
||||
* block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
|
||||
* indentless_sequence ::= (BLOCK-ENTRY block_node?)+
|
||||
* block_mapping ::= BLOCK-MAPPING_START
|
||||
* ((KEY block_node_or_indentless_sequence?)?
|
||||
* (VALUE block_node_or_indentless_sequence?)?)*
|
||||
* BLOCK-END
|
||||
* flow_sequence ::= FLOW-SEQUENCE-START
|
||||
* (flow_sequence_entry FLOW-ENTRY)*
|
||||
* flow_sequence_entry?
|
||||
* FLOW-SEQUENCE-END
|
||||
* flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||
* flow_mapping ::= FLOW-MAPPING-START
|
||||
* (flow_mapping_entry FLOW-ENTRY)*
|
||||
* flow_mapping_entry?
|
||||
* FLOW-MAPPING-END
|
||||
* flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||
* FIRST sets:
|
||||
* stream: { STREAM-START }
|
||||
* explicit_document: { DIRECTIVE DOCUMENT-START }
|
||||
* implicit_document: FIRST(block_node)
|
||||
* block_node: { ALIAS TAG ANCHOR SCALAR BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START }
|
||||
* flow_node: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START }
|
||||
* block_content: { BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START SCALAR }
|
||||
* flow_content: { FLOW-SEQUENCE-START FLOW-MAPPING-START SCALAR }
|
||||
* block_collection: { BLOCK-SEQUENCE-START BLOCK-MAPPING-START }
|
||||
* flow_collection: { FLOW-SEQUENCE-START FLOW-MAPPING-START }
|
||||
* block_sequence: { BLOCK-SEQUENCE-START }
|
||||
* block_mapping: { BLOCK-MAPPING-START }
|
||||
* block_node_or_indentless_sequence: { ALIAS ANCHOR TAG SCALAR BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START BLOCK-ENTRY }
|
||||
* indentless_sequence: { ENTRY }
|
||||
* flow_collection: { FLOW-SEQUENCE-START FLOW-MAPPING-START }
|
||||
* flow_sequence: { FLOW-SEQUENCE-START }
|
||||
* flow_mapping: { FLOW-MAPPING-START }
|
||||
* flow_sequence_entry: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START KEY }
|
||||
* flow_mapping_entry: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START KEY }
|
||||
* </pre>
|
||||
*
|
||||
* Since writing a recursive-descendant parser is a straightforward task, we do
|
||||
* not give many comments here.
|
||||
*/
|
||||
public class ParserImpl implements Parser {
|
||||
private static final Map<String, String> DEFAULT_TAGS = new HashMap<String, String>();
|
||||
static {
|
||||
DEFAULT_TAGS.put("!", "!");
|
||||
DEFAULT_TAGS.put("!!", Tag.PREFIX);
|
||||
}
|
||||
|
||||
protected final Scanner scanner;
|
||||
private Event currentEvent;
|
||||
private final ArrayStack<Production> states;
|
||||
private final ArrayStack<Mark> marks;
|
||||
private Production state;
|
||||
private VersionTagsTuple directives;
|
||||
|
||||
public ParserImpl(StreamReader reader) {
|
||||
this(new ScannerImpl(reader));
|
||||
}
|
||||
|
||||
public ParserImpl(Scanner scanner) {
|
||||
this.scanner = scanner;
|
||||
currentEvent = null;
|
||||
directives = new VersionTagsTuple(null, new HashMap<String, String>(DEFAULT_TAGS));
|
||||
states = new ArrayStack<Production>(100);
|
||||
marks = new ArrayStack<Mark>(10);
|
||||
state = new ParseStreamStart();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the type of the next event.
|
||||
*/
|
||||
public boolean checkEvent(Event.ID choice) {
|
||||
peekEvent();
|
||||
return currentEvent != null && currentEvent.is(choice);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next event.
|
||||
*/
|
||||
public Event peekEvent() {
|
||||
if (currentEvent == null) {
|
||||
if (state != null) {
|
||||
currentEvent = state.produce();
|
||||
}
|
||||
}
|
||||
return currentEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next event and proceed further.
|
||||
*/
|
||||
public Event getEvent() {
|
||||
peekEvent();
|
||||
Event value = currentEvent;
|
||||
currentEvent = null;
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
|
||||
* implicit_document ::= block_node DOCUMENT-END*
|
||||
* explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
|
||||
* </pre>
|
||||
*/
|
||||
private class ParseStreamStart implements Production {
|
||||
public Event produce() {
|
||||
// Parse the stream start.
|
||||
StreamStartToken token = (StreamStartToken) scanner.getToken();
|
||||
Event event = new StreamStartEvent(token.getStartMark(), token.getEndMark());
|
||||
// Prepare the next state.
|
||||
state = new ParseImplicitDocumentStart();
|
||||
return event;
|
||||
}
|
||||
}
|
||||
|
||||
private class ParseImplicitDocumentStart implements Production {
|
||||
public Event produce() {
|
||||
// Parse an implicit document.
|
||||
if (!scanner.checkToken(Token.ID.Directive, Token.ID.DocumentStart, Token.ID.StreamEnd)) {
|
||||
directives = new VersionTagsTuple(null, DEFAULT_TAGS);
|
||||
Token token = scanner.peekToken();
|
||||
Mark startMark = token.getStartMark();
|
||||
Mark endMark = startMark;
|
||||
Event event = new DocumentStartEvent(startMark, endMark, false, null, null);
|
||||
// Prepare the next state.
|
||||
states.push(new ParseDocumentEnd());
|
||||
state = new ParseBlockNode();
|
||||
return event;
|
||||
} else {
|
||||
Production p = new ParseDocumentStart();
|
||||
return p.produce();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ParseDocumentStart implements Production {
|
||||
public Event produce() {
|
||||
// Parse any extra document end indicators.
|
||||
while (scanner.checkToken(Token.ID.DocumentEnd)) {
|
||||
scanner.getToken();
|
||||
}
|
||||
// Parse an explicit document.
|
||||
Event event;
|
||||
if (!scanner.checkToken(Token.ID.StreamEnd)) {
|
||||
Token token = scanner.peekToken();
|
||||
Mark startMark = token.getStartMark();
|
||||
VersionTagsTuple tuple = processDirectives();
|
||||
if (!scanner.checkToken(Token.ID.DocumentStart)) {
|
||||
throw new ParserException(null, null, "expected '<document start>', but found '"
|
||||
+ scanner.peekToken().getTokenId() + "'", scanner.peekToken().getStartMark());
|
||||
}
|
||||
token = scanner.getToken();
|
||||
Mark endMark = token.getEndMark();
|
||||
event = new DocumentStartEvent(startMark, endMark, true, tuple.getVersion(),
|
||||
tuple.getTags());
|
||||
states.push(new ParseDocumentEnd());
|
||||
state = new ParseDocumentContent();
|
||||
} else {
|
||||
// Parse the end of the stream.
|
||||
StreamEndToken token = (StreamEndToken) scanner.getToken();
|
||||
event = new StreamEndEvent(token.getStartMark(), token.getEndMark());
|
||||
if (!states.isEmpty()) {
|
||||
throw new YAMLException("Unexpected end of stream. States left: " + states);
|
||||
}
|
||||
if (!marks.isEmpty()) {
|
||||
throw new YAMLException("Unexpected end of stream. Marks left: " + marks);
|
||||
}
|
||||
state = null;
|
||||
}
|
||||
return event;
|
||||
}
|
||||
}
|
||||
|
||||
private class ParseDocumentEnd implements Production {
|
||||
public Event produce() {
|
||||
// Parse the document end.
|
||||
Token token = scanner.peekToken();
|
||||
Mark startMark = token.getStartMark();
|
||||
Mark endMark = startMark;
|
||||
boolean explicit = false;
|
||||
if (scanner.checkToken(Token.ID.DocumentEnd)) {
|
||||
token = scanner.getToken();
|
||||
endMark = token.getEndMark();
|
||||
explicit = true;
|
||||
}
|
||||
Event event = new DocumentEndEvent(startMark, endMark, explicit);
|
||||
// Prepare the next state.
|
||||
state = new ParseDocumentStart();
|
||||
return event;
|
||||
}
|
||||
}
|
||||
|
||||
private class ParseDocumentContent implements Production {
|
||||
public Event produce() {
|
||||
Event event;
|
||||
if (scanner.checkToken(Token.ID.Directive, Token.ID.DocumentStart,
|
||||
Token.ID.DocumentEnd, Token.ID.StreamEnd)) {
|
||||
event = processEmptyScalar(scanner.peekToken().getStartMark());
|
||||
state = states.pop();
|
||||
return event;
|
||||
} else {
|
||||
Production p = new ParseBlockNode();
|
||||
return p.produce();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private VersionTagsTuple processDirectives() {
|
||||
Version yamlVersion = null;
|
||||
HashMap<String, String> tagHandles = new HashMap<String, String>();
|
||||
while (scanner.checkToken(Token.ID.Directive)) {
|
||||
@SuppressWarnings("rawtypes")
|
||||
DirectiveToken token = (DirectiveToken) scanner.getToken();
|
||||
if (token.getName().equals("YAML")) {
|
||||
if (yamlVersion != null) {
|
||||
throw new ParserException(null, null, "found duplicate YAML directive",
|
||||
token.getStartMark());
|
||||
}
|
||||
List<Integer> value = (List<Integer>) token.getValue();
|
||||
Integer major = value.get(0);
|
||||
if (major != 1) {
|
||||
throw new ParserException(null, null,
|
||||
"found incompatible YAML document (version 1.* is required)",
|
||||
token.getStartMark());
|
||||
}
|
||||
Integer minor = value.get(1);
|
||||
switch (minor) {
|
||||
case 0:
|
||||
yamlVersion = Version.V1_0;
|
||||
break;
|
||||
|
||||
default:
|
||||
yamlVersion = Version.V1_1;
|
||||
break;
|
||||
}
|
||||
} else if (token.getName().equals("TAG")) {
|
||||
List<String> value = (List<String>) token.getValue();
|
||||
String handle = value.get(0);
|
||||
String prefix = value.get(1);
|
||||
if (tagHandles.containsKey(handle)) {
|
||||
throw new ParserException(null, null, "duplicate tag handle " + handle,
|
||||
token.getStartMark());
|
||||
}
|
||||
tagHandles.put(handle, prefix);
|
||||
}
|
||||
}
|
||||
if (yamlVersion != null || !tagHandles.isEmpty()) {
|
||||
// directives in the document found - drop the previous
|
||||
for (String key : DEFAULT_TAGS.keySet()) {
|
||||
// do not overwrite re-defined tags
|
||||
if (!tagHandles.containsKey(key)) {
|
||||
tagHandles.put(key, DEFAULT_TAGS.get(key));
|
||||
}
|
||||
}
|
||||
directives = new VersionTagsTuple(yamlVersion, tagHandles);
|
||||
}
|
||||
return directives;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* block_node_or_indentless_sequence ::= ALIAS
|
||||
* | properties (block_content | indentless_block_sequence)?
|
||||
* | block_content
|
||||
* | indentless_block_sequence
|
||||
* block_node ::= ALIAS
|
||||
* | properties block_content?
|
||||
* | block_content
|
||||
* flow_node ::= ALIAS
|
||||
* | properties flow_content?
|
||||
* | flow_content
|
||||
* properties ::= TAG ANCHOR? | ANCHOR TAG?
|
||||
* block_content ::= block_collection | flow_collection | SCALAR
|
||||
* flow_content ::= flow_collection | SCALAR
|
||||
* block_collection ::= block_sequence | block_mapping
|
||||
* flow_collection ::= flow_sequence | flow_mapping
|
||||
* </pre>
|
||||
*/
|
||||
|
||||
private class ParseBlockNode implements Production {
|
||||
public Event produce() {
|
||||
return parseNode(true, false);
|
||||
}
|
||||
}
|
||||
|
||||
private Event parseFlowNode() {
|
||||
return parseNode(false, false);
|
||||
}
|
||||
|
||||
private Event parseBlockNodeOrIndentlessSequence() {
|
||||
return parseNode(true, true);
|
||||
}
|
||||
|
||||
private Event parseNode(boolean block, boolean indentlessSequence) {
|
||||
Event event;
|
||||
Mark startMark = null;
|
||||
Mark endMark = null;
|
||||
Mark tagMark = null;
|
||||
if (scanner.checkToken(Token.ID.Alias)) {
|
||||
AliasToken token = (AliasToken) scanner.getToken();
|
||||
event = new AliasEvent(token.getValue(), token.getStartMark(), token.getEndMark());
|
||||
state = states.pop();
|
||||
} else {
|
||||
String anchor = null;
|
||||
TagTuple tagTokenTag = null;
|
||||
if (scanner.checkToken(Token.ID.Anchor)) {
|
||||
AnchorToken token = (AnchorToken) scanner.getToken();
|
||||
startMark = token.getStartMark();
|
||||
endMark = token.getEndMark();
|
||||
anchor = token.getValue();
|
||||
if (scanner.checkToken(Token.ID.Tag)) {
|
||||
TagToken tagToken = (TagToken) scanner.getToken();
|
||||
tagMark = tagToken.getStartMark();
|
||||
endMark = tagToken.getEndMark();
|
||||
tagTokenTag = tagToken.getValue();
|
||||
}
|
||||
} else if (scanner.checkToken(Token.ID.Tag)) {
|
||||
TagToken tagToken = (TagToken) scanner.getToken();
|
||||
startMark = tagToken.getStartMark();
|
||||
tagMark = startMark;
|
||||
endMark = tagToken.getEndMark();
|
||||
tagTokenTag = tagToken.getValue();
|
||||
if (scanner.checkToken(Token.ID.Anchor)) {
|
||||
AnchorToken token = (AnchorToken) scanner.getToken();
|
||||
endMark = token.getEndMark();
|
||||
anchor = token.getValue();
|
||||
}
|
||||
}
|
||||
String tag = null;
|
||||
if (tagTokenTag != null) {
|
||||
String handle = tagTokenTag.getHandle();
|
||||
String suffix = tagTokenTag.getSuffix();
|
||||
if (handle != null) {
|
||||
if (!directives.getTags().containsKey(handle)) {
|
||||
throw new ParserException("while parsing a node", startMark,
|
||||
"found undefined tag handle " + handle, tagMark);
|
||||
}
|
||||
tag = directives.getTags().get(handle) + suffix;
|
||||
} else {
|
||||
tag = suffix;
|
||||
}
|
||||
}
|
||||
if (startMark == null) {
|
||||
startMark = scanner.peekToken().getStartMark();
|
||||
endMark = startMark;
|
||||
}
|
||||
event = null;
|
||||
boolean implicit = tag == null || tag.equals("!");
|
||||
if (indentlessSequence && scanner.checkToken(Token.ID.BlockEntry)) {
|
||||
endMark = scanner.peekToken().getEndMark();
|
||||
event = new SequenceStartEvent(anchor, tag, implicit, startMark, endMark,
|
||||
DumperOptions.FlowStyle.BLOCK);
|
||||
state = new ParseIndentlessSequenceEntry();
|
||||
} else {
|
||||
if (scanner.checkToken(Token.ID.Scalar)) {
|
||||
ScalarToken token = (ScalarToken) scanner.getToken();
|
||||
endMark = token.getEndMark();
|
||||
ImplicitTuple implicitValues;
|
||||
if ((token.getPlain() && tag == null) || "!".equals(tag)) {
|
||||
implicitValues = new ImplicitTuple(true, false);
|
||||
} else if (tag == null) {
|
||||
implicitValues = new ImplicitTuple(false, true);
|
||||
} else {
|
||||
implicitValues = new ImplicitTuple(false, false);
|
||||
}
|
||||
event = new ScalarEvent(anchor, tag, implicitValues, token.getValue(),
|
||||
startMark, endMark, token.getStyle());
|
||||
state = states.pop();
|
||||
} else if (scanner.checkToken(Token.ID.FlowSequenceStart)) {
|
||||
endMark = scanner.peekToken().getEndMark();
|
||||
event = new SequenceStartEvent(anchor, tag, implicit, startMark, endMark,
|
||||
DumperOptions.FlowStyle.FLOW);
|
||||
state = new ParseFlowSequenceFirstEntry();
|
||||
} else if (scanner.checkToken(Token.ID.FlowMappingStart)) {
|
||||
endMark = scanner.peekToken().getEndMark();
|
||||
event = new MappingStartEvent(anchor, tag, implicit, startMark, endMark,
|
||||
DumperOptions.FlowStyle.FLOW);
|
||||
state = new ParseFlowMappingFirstKey();
|
||||
} else if (block && scanner.checkToken(Token.ID.BlockSequenceStart)) {
|
||||
endMark = scanner.peekToken().getStartMark();
|
||||
event = new SequenceStartEvent(anchor, tag, implicit, startMark, endMark,
|
||||
DumperOptions.FlowStyle.BLOCK);
|
||||
state = new ParseBlockSequenceFirstEntry();
|
||||
} else if (block && scanner.checkToken(Token.ID.BlockMappingStart)) {
|
||||
endMark = scanner.peekToken().getStartMark();
|
||||
event = new MappingStartEvent(anchor, tag, implicit, startMark, endMark,
|
||||
DumperOptions.FlowStyle.BLOCK);
|
||||
state = new ParseBlockMappingFirstKey();
|
||||
} else if (anchor != null || tag != null) {
|
||||
// Empty scalars are allowed even if a tag or an anchor is
|
||||
// specified.
|
||||
event = new ScalarEvent(anchor, tag, new ImplicitTuple(implicit, false), "",
|
||||
startMark, endMark, DumperOptions.ScalarStyle.PLAIN);
|
||||
state = states.pop();
|
||||
} else {
|
||||
String node;
|
||||
if (block) {
|
||||
node = "block";
|
||||
} else {
|
||||
node = "flow";
|
||||
}
|
||||
Token token = scanner.peekToken();
|
||||
throw new ParserException("while parsing a " + node + " node", startMark,
|
||||
"expected the node content, but found '" + token.getTokenId() + "'",
|
||||
token.getStartMark());
|
||||
}
|
||||
}
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)*
|
||||
// BLOCK-END
|
||||
|
||||
private class ParseBlockSequenceFirstEntry implements Production {
|
||||
public Event produce() {
|
||||
Token token = scanner.getToken();
|
||||
marks.push(token.getStartMark());
|
||||
return new ParseBlockSequenceEntry().produce();
|
||||
}
|
||||
}
|
||||
|
||||
private class ParseBlockSequenceEntry implements Production {
|
||||
public Event produce() {
|
||||
if (scanner.checkToken(Token.ID.BlockEntry)) {
|
||||
BlockEntryToken token = (BlockEntryToken) scanner.getToken();
|
||||
if (!scanner.checkToken(Token.ID.BlockEntry, Token.ID.BlockEnd)) {
|
||||
states.push(new ParseBlockSequenceEntry());
|
||||
return new ParseBlockNode().produce();
|
||||
} else {
|
||||
state = new ParseBlockSequenceEntry();
|
||||
return processEmptyScalar(token.getEndMark());
|
||||
}
|
||||
}
|
||||
if (!scanner.checkToken(Token.ID.BlockEnd)) {
|
||||
Token token = scanner.peekToken();
|
||||
throw new ParserException("while parsing a block collection", marks.pop(),
|
||||
"expected <block end>, but found '" + token.getTokenId() + "'",
|
||||
token.getStartMark());
|
||||
}
|
||||
Token token = scanner.getToken();
|
||||
Event event = new SequenceEndEvent(token.getStartMark(), token.getEndMark());
|
||||
state = states.pop();
|
||||
marks.pop();
|
||||
return event;
|
||||
}
|
||||
}
|
||||
|
||||
// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
|
||||
|
||||
private class ParseIndentlessSequenceEntry implements Production {
|
||||
public Event produce() {
|
||||
if (scanner.checkToken(Token.ID.BlockEntry)) {
|
||||
Token token = scanner.getToken();
|
||||
if (!scanner.checkToken(Token.ID.BlockEntry, Token.ID.Key, Token.ID.Value,
|
||||
Token.ID.BlockEnd)) {
|
||||
states.push(new ParseIndentlessSequenceEntry());
|
||||
return new ParseBlockNode().produce();
|
||||
} else {
|
||||
state = new ParseIndentlessSequenceEntry();
|
||||
return processEmptyScalar(token.getEndMark());
|
||||
}
|
||||
}
|
||||
Token token = scanner.peekToken();
|
||||
Event event = new SequenceEndEvent(token.getStartMark(), token.getEndMark());
|
||||
state = states.pop();
|
||||
return event;
|
||||
}
|
||||
}
|
||||
|
||||
private class ParseBlockMappingFirstKey implements Production {
|
||||
public Event produce() {
|
||||
Token token = scanner.getToken();
|
||||
marks.push(token.getStartMark());
|
||||
return new ParseBlockMappingKey().produce();
|
||||
}
|
||||
}
|
||||
|
||||
private class ParseBlockMappingKey implements Production {
|
||||
public Event produce() {
|
||||
if (scanner.checkToken(Token.ID.Key)) {
|
||||
Token token = scanner.getToken();
|
||||
if (!scanner.checkToken(Token.ID.Key, Token.ID.Value, Token.ID.BlockEnd)) {
|
||||
states.push(new ParseBlockMappingValue());
|
||||
return parseBlockNodeOrIndentlessSequence();
|
||||
} else {
|
||||
state = new ParseBlockMappingValue();
|
||||
return processEmptyScalar(token.getEndMark());
|
||||
}
|
||||
}
|
||||
if (!scanner.checkToken(Token.ID.BlockEnd)) {
|
||||
Token token = scanner.peekToken();
|
||||
throw new ParserException("while parsing a block mapping", marks.pop(),
|
||||
"expected <block end>, but found '" + token.getTokenId() + "'",
|
||||
token.getStartMark());
|
||||
}
|
||||
Token token = scanner.getToken();
|
||||
Event event = new MappingEndEvent(token.getStartMark(), token.getEndMark());
|
||||
state = states.pop();
|
||||
marks.pop();
|
||||
return event;
|
||||
}
|
||||
}
|
||||
|
||||
private class ParseBlockMappingValue implements Production {
|
||||
public Event produce() {
|
||||
if (scanner.checkToken(Token.ID.Value)) {
|
||||
Token token = scanner.getToken();
|
||||
if (!scanner.checkToken(Token.ID.Key, Token.ID.Value, Token.ID.BlockEnd)) {
|
||||
states.push(new ParseBlockMappingKey());
|
||||
return parseBlockNodeOrIndentlessSequence();
|
||||
} else {
|
||||
state = new ParseBlockMappingKey();
|
||||
return processEmptyScalar(token.getEndMark());
|
||||
}
|
||||
}
|
||||
state = new ParseBlockMappingKey();
|
||||
Token token = scanner.peekToken();
|
||||
return processEmptyScalar(token.getStartMark());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* flow_sequence ::= FLOW-SEQUENCE-START
|
||||
* (flow_sequence_entry FLOW-ENTRY)*
|
||||
* flow_sequence_entry?
|
||||
* FLOW-SEQUENCE-END
|
||||
* flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||
* Note that while production rules for both flow_sequence_entry and
|
||||
* flow_mapping_entry are equal, their interpretations are different.
|
||||
* For `flow_sequence_entry`, the part `KEY flow_node? (VALUE flow_node?)?`
|
||||
* generate an inline mapping (set syntax).
|
||||
* </pre>
|
||||
*/
|
||||
private class ParseFlowSequenceFirstEntry implements Production {
|
||||
public Event produce() {
|
||||
Token token = scanner.getToken();
|
||||
marks.push(token.getStartMark());
|
||||
return new ParseFlowSequenceEntry(true).produce();
|
||||
}
|
||||
}
|
||||
|
||||
private class ParseFlowSequenceEntry implements Production {
|
||||
private boolean first = false;
|
||||
|
||||
public ParseFlowSequenceEntry(boolean first) {
|
||||
this.first = first;
|
||||
}
|
||||
|
||||
public Event produce() {
|
||||
if (!scanner.checkToken(Token.ID.FlowSequenceEnd)) {
|
||||
if (!first) {
|
||||
if (scanner.checkToken(Token.ID.FlowEntry)) {
|
||||
scanner.getToken();
|
||||
} else {
|
||||
Token token = scanner.peekToken();
|
||||
throw new ParserException("while parsing a flow sequence", marks.pop(),
|
||||
"expected ',' or ']', but got " + token.getTokenId(),
|
||||
token.getStartMark());
|
||||
}
|
||||
}
|
||||
if (scanner.checkToken(Token.ID.Key)) {
|
||||
Token token = scanner.peekToken();
|
||||
Event event = new MappingStartEvent(null, null, true, token.getStartMark(),
|
||||
token.getEndMark(), DumperOptions.FlowStyle.FLOW);
|
||||
state = new ParseFlowSequenceEntryMappingKey();
|
||||
return event;
|
||||
} else if (!scanner.checkToken(Token.ID.FlowSequenceEnd)) {
|
||||
states.push(new ParseFlowSequenceEntry(false));
|
||||
return parseFlowNode();
|
||||
}
|
||||
}
|
||||
Token token = scanner.getToken();
|
||||
Event event = new SequenceEndEvent(token.getStartMark(), token.getEndMark());
|
||||
state = states.pop();
|
||||
marks.pop();
|
||||
return event;
|
||||
}
|
||||
}
|
||||
|
||||
private class ParseFlowSequenceEntryMappingKey implements Production {
|
||||
public Event produce() {
|
||||
Token token = scanner.getToken();
|
||||
if (!scanner.checkToken(Token.ID.Value, Token.ID.FlowEntry, Token.ID.FlowSequenceEnd)) {
|
||||
states.push(new ParseFlowSequenceEntryMappingValue());
|
||||
return parseFlowNode();
|
||||
} else {
|
||||
state = new ParseFlowSequenceEntryMappingValue();
|
||||
return processEmptyScalar(token.getEndMark());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ParseFlowSequenceEntryMappingValue implements Production {
|
||||
public Event produce() {
|
||||
if (scanner.checkToken(Token.ID.Value)) {
|
||||
Token token = scanner.getToken();
|
||||
if (!scanner.checkToken(Token.ID.FlowEntry, Token.ID.FlowSequenceEnd)) {
|
||||
states.push(new ParseFlowSequenceEntryMappingEnd());
|
||||
return parseFlowNode();
|
||||
} else {
|
||||
state = new ParseFlowSequenceEntryMappingEnd();
|
||||
return processEmptyScalar(token.getEndMark());
|
||||
}
|
||||
} else {
|
||||
state = new ParseFlowSequenceEntryMappingEnd();
|
||||
Token token = scanner.peekToken();
|
||||
return processEmptyScalar(token.getStartMark());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ParseFlowSequenceEntryMappingEnd implements Production {
|
||||
public Event produce() {
|
||||
state = new ParseFlowSequenceEntry(false);
|
||||
Token token = scanner.peekToken();
|
||||
return new MappingEndEvent(token.getStartMark(), token.getEndMark());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* flow_mapping ::= FLOW-MAPPING-START
|
||||
* (flow_mapping_entry FLOW-ENTRY)*
|
||||
* flow_mapping_entry?
|
||||
* FLOW-MAPPING-END
|
||||
* flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||
* </pre>
|
||||
*/
|
||||
private class ParseFlowMappingFirstKey implements Production {
|
||||
public Event produce() {
|
||||
Token token = scanner.getToken();
|
||||
marks.push(token.getStartMark());
|
||||
return new ParseFlowMappingKey(true).produce();
|
||||
}
|
||||
}
|
||||
|
||||
private class ParseFlowMappingKey implements Production {
|
||||
private boolean first = false;
|
||||
|
||||
public ParseFlowMappingKey(boolean first) {
|
||||
this.first = first;
|
||||
}
|
||||
|
||||
public Event produce() {
|
||||
if (!scanner.checkToken(Token.ID.FlowMappingEnd)) {
|
||||
if (!first) {
|
||||
if (scanner.checkToken(Token.ID.FlowEntry)) {
|
||||
scanner.getToken();
|
||||
} else {
|
||||
Token token = scanner.peekToken();
|
||||
throw new ParserException("while parsing a flow mapping", marks.pop(),
|
||||
"expected ',' or '}', but got " + token.getTokenId(),
|
||||
token.getStartMark());
|
||||
}
|
||||
}
|
||||
if (scanner.checkToken(Token.ID.Key)) {
|
||||
Token token = scanner.getToken();
|
||||
if (!scanner.checkToken(Token.ID.Value, Token.ID.FlowEntry,
|
||||
Token.ID.FlowMappingEnd)) {
|
||||
states.push(new ParseFlowMappingValue());
|
||||
return parseFlowNode();
|
||||
} else {
|
||||
state = new ParseFlowMappingValue();
|
||||
return processEmptyScalar(token.getEndMark());
|
||||
}
|
||||
} else if (!scanner.checkToken(Token.ID.FlowMappingEnd)) {
|
||||
states.push(new ParseFlowMappingEmptyValue());
|
||||
return parseFlowNode();
|
||||
}
|
||||
}
|
||||
Token token = scanner.getToken();
|
||||
Event event = new MappingEndEvent(token.getStartMark(), token.getEndMark());
|
||||
state = states.pop();
|
||||
marks.pop();
|
||||
return event;
|
||||
}
|
||||
}
|
||||
|
||||
private class ParseFlowMappingValue implements Production {
|
||||
public Event produce() {
|
||||
if (scanner.checkToken(Token.ID.Value)) {
|
||||
Token token = scanner.getToken();
|
||||
if (!scanner.checkToken(Token.ID.FlowEntry, Token.ID.FlowMappingEnd)) {
|
||||
states.push(new ParseFlowMappingKey(false));
|
||||
return parseFlowNode();
|
||||
} else {
|
||||
state = new ParseFlowMappingKey(false);
|
||||
return processEmptyScalar(token.getEndMark());
|
||||
}
|
||||
} else {
|
||||
state = new ParseFlowMappingKey(false);
|
||||
Token token = scanner.peekToken();
|
||||
return processEmptyScalar(token.getStartMark());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ParseFlowMappingEmptyValue implements Production {
|
||||
public Event produce() {
|
||||
state = new ParseFlowMappingKey(false);
|
||||
return processEmptyScalar(scanner.peekToken().getStartMark());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* block_mapping ::= BLOCK-MAPPING_START
|
||||
* ((KEY block_node_or_indentless_sequence?)?
|
||||
* (VALUE block_node_or_indentless_sequence?)?)*
|
||||
* BLOCK-END
|
||||
* </pre>
|
||||
*/
|
||||
private Event processEmptyScalar(Mark mark) {
|
||||
return new ScalarEvent(null, null, new ImplicitTuple(true, false), "", mark, mark, DumperOptions.ScalarStyle.PLAIN);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.parser;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.Event;
|
||||
|
||||
/**
|
||||
* Helper for {@link ParserImpl}. A grammar rule to apply given the symbols on
|
||||
* top of its stack and the next input token
|
||||
*
|
||||
* @see <a href="http://en.wikipedia.org/wiki/LL_parser"></a>
|
||||
*/
|
||||
interface Production {
|
||||
Event produce();
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.parser;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.DumperOptions.Version;
|
||||
|
||||
/**
|
||||
* Store the internal state for directives
|
||||
*/
|
||||
class VersionTagsTuple {
|
||||
private Version version;
|
||||
private Map<String, String> tags;
|
||||
|
||||
public VersionTagsTuple(Version version, Map<String, String> tags) {
|
||||
this.version = version;
|
||||
this.tags = tags;
|
||||
}
|
||||
|
||||
public Version getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public Map<String, String> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("VersionTagsTuple<%s, %s>", version, tags);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.reader;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.YAMLException;
|
||||
|
||||
public class ReaderException extends YAMLException {
|
||||
private static final long serialVersionUID = 8710781187529689083L;
|
||||
private final String name;
|
||||
private final int codePoint;
|
||||
private final int position;
|
||||
|
||||
public ReaderException(String name, int position, int codePoint, String message) {
|
||||
super(message);
|
||||
this.name = name;
|
||||
this.codePoint = codePoint;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getCodePoint() {
|
||||
return codePoint;
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final String s = new String(Character.toChars(codePoint));
|
||||
return "unacceptable code point '" + s + "' (0x"
|
||||
+ Integer.toHexString(codePoint).toUpperCase() + ") " + getMessage()
|
||||
+ "\nin \"" + name + "\", position " + position;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,237 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.reader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.util.Arrays;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.YAMLException;
|
||||
import io.jenkins.plugins.casc.snakeyaml.scanner.Constant;
|
||||
|
||||
/**
|
||||
* Reader: checks if code points are in allowed range. Returns '\0' when end of
|
||||
* data has been reached.
|
||||
*/
|
||||
public class StreamReader {
|
||||
private String name;
|
||||
private final Reader stream;
|
||||
/**
|
||||
* Read data (as a moving window for input stream)
|
||||
*/
|
||||
private int[] dataWindow;
|
||||
|
||||
/**
|
||||
* Real length of the data in dataWindow
|
||||
*/
|
||||
private int dataLength;
|
||||
|
||||
/**
|
||||
* The variable points to the current position in the data array
|
||||
*/
|
||||
private int pointer = 0;
|
||||
private boolean eof;
|
||||
/**
|
||||
* index is only required to implement 1024 key length restriction
|
||||
* http://yaml.org/spec/1.1/#simple key/
|
||||
* It must count code points, but it counts characters (to be fixed)
|
||||
*/
|
||||
private int index = 0; // in code points
|
||||
private int line = 0;
|
||||
private int column = 0; //in code points
|
||||
private char[] buffer; // temp buffer for one read operation (to avoid
|
||||
// creating the array in stack)
|
||||
|
||||
private static final int BUFFER_SIZE = 1025;
|
||||
|
||||
public StreamReader(String stream) {
|
||||
this(new StringReader(stream));
|
||||
this.name = "'string'";
|
||||
}
|
||||
|
||||
public StreamReader(Reader reader) {
|
||||
this.name = "'reader'";
|
||||
this.dataWindow = new int[0];
|
||||
this.dataLength = 0;
|
||||
this.stream = reader;
|
||||
this.eof = false;
|
||||
this.buffer = new char[BUFFER_SIZE];
|
||||
}
|
||||
|
||||
public static boolean isPrintable(final String data) {
|
||||
final int length = data.length();
|
||||
for (int offset = 0; offset < length; ) {
|
||||
final int codePoint = data.codePointAt(offset);
|
||||
|
||||
if (!isPrintable(codePoint)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
offset += Character.charCount(codePoint);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isPrintable(final int c) {
|
||||
return (c >= 0x20 && c <= 0x7E) || c == 0x9 || c == 0xA || c == 0xD || c == 0x85
|
||||
|| (c >= 0xA0 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD)
|
||||
|| (c >= 0x10000 && c <= 0x10FFFF);
|
||||
}
|
||||
|
||||
public Mark getMark() {
|
||||
return new Mark(name, this.index, this.line, this.column, this.dataWindow, this.pointer);
|
||||
}
|
||||
|
||||
public void forward() {
|
||||
forward(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* read the next length characters and move the pointer.
|
||||
* if the last character is high surrogate one more character will be read
|
||||
*
|
||||
* @param length amount of characters to move forward
|
||||
*/
|
||||
public void forward(int length) {
|
||||
for (int i = 0; i < length && ensureEnoughData(); i++) {
|
||||
int c = dataWindow[pointer++];
|
||||
this.index++;
|
||||
if (Constant.LINEBR.has(c)
|
||||
|| (c == '\r' && (ensureEnoughData() && dataWindow[pointer] != '\n'))) {
|
||||
this.line++;
|
||||
this.column = 0;
|
||||
} else if (c != 0xFEFF) {
|
||||
this.column++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int peek() {
|
||||
return (ensureEnoughData()) ? dataWindow[pointer] : '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Peek the next index-th code point
|
||||
*
|
||||
* @param index to peek
|
||||
* @return the next index-th code point
|
||||
*/
|
||||
public int peek(int index) {
|
||||
return (ensureEnoughData(index)) ? dataWindow[pointer + index] : '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* peek the next length code points
|
||||
*
|
||||
* @param length amount of the characters to peek
|
||||
* @return the next length code points
|
||||
*/
|
||||
public String prefix(int length) {
|
||||
if (length == 0) {
|
||||
return "";
|
||||
} else if (ensureEnoughData(length)) {
|
||||
return new String(this.dataWindow, pointer, length);
|
||||
} else {
|
||||
return new String(this.dataWindow, pointer,
|
||||
Math.min(length, dataLength - pointer));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* prefix(length) immediately followed by forward(length)
|
||||
* @param length amount of characters to get
|
||||
* @return the next length code points
|
||||
*/
|
||||
public String prefixForward(int length) {
|
||||
final String prefix = prefix(length);
|
||||
this.pointer += length;
|
||||
this.index += length;
|
||||
// prefix never contains new line characters
|
||||
this.column += length;
|
||||
return prefix;
|
||||
}
|
||||
|
||||
private boolean ensureEnoughData() {
|
||||
return ensureEnoughData(0);
|
||||
}
|
||||
|
||||
private boolean ensureEnoughData(int size) {
|
||||
if (!eof && pointer + size >= dataLength) {
|
||||
update();
|
||||
}
|
||||
return (this.pointer + size) < dataLength;
|
||||
}
|
||||
|
||||
private void update() {
|
||||
try {
|
||||
int read = stream.read(buffer, 0, BUFFER_SIZE - 1);
|
||||
if (read > 0) {
|
||||
int cpIndex = (dataLength - pointer);
|
||||
dataWindow = Arrays.copyOfRange(dataWindow, pointer, dataLength + read);
|
||||
|
||||
if (Character.isHighSurrogate(buffer[read - 1])) {
|
||||
if (stream.read(buffer, read, 1) == -1) {
|
||||
eof = true;
|
||||
} else {
|
||||
read++;
|
||||
}
|
||||
}
|
||||
|
||||
int nonPrintable = ' ';
|
||||
for (int i = 0; i < read; cpIndex++) {
|
||||
int codePoint = Character.codePointAt(buffer, i);
|
||||
dataWindow[cpIndex] = codePoint;
|
||||
if (isPrintable(codePoint)) {
|
||||
i += Character.charCount(codePoint);
|
||||
} else {
|
||||
nonPrintable = codePoint;
|
||||
i = read;
|
||||
}
|
||||
}
|
||||
|
||||
dataLength = cpIndex;
|
||||
pointer = 0;
|
||||
if (nonPrintable != ' ') {
|
||||
throw new ReaderException(name, cpIndex - 1, nonPrintable,
|
||||
"special characters are not allowed");
|
||||
}
|
||||
} else {
|
||||
eof = true;
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
throw new YAMLException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getColumn() {
|
||||
return column;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return current position as number (in characters) from the beginning of the stream
|
||||
*/
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.reader;
|
||||
|
||||
/**
|
||||
version: 1.1 / 2007-01-25
|
||||
- changed BOM recognition ordering (longer boms first)
|
||||
|
||||
Original pseudocode : Thomas Weidenfeller
|
||||
Implementation tweaked: Aki Nieminen
|
||||
Implementation changed: Andrey Somov
|
||||
* UTF-32 removed because it is not supported by YAML
|
||||
* no default encoding
|
||||
|
||||
http://www.unicode.org/unicode/faq/utf_bom.html
|
||||
BOMs:
|
||||
00 00 FE FF = UTF-32, big-endian
|
||||
FF FE 00 00 = UTF-32, little-endian
|
||||
EF BB BF = UTF-8,
|
||||
FE FF = UTF-16, big-endian
|
||||
FF FE = UTF-16, little-endian
|
||||
|
||||
Win2k Notepad:
|
||||
Unicode format = UTF-16LE
|
||||
***/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PushbackInputStream;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.CodingErrorAction;
|
||||
|
||||
/**
|
||||
* Generic unicode textreader, which will use BOM mark to identify the encoding
|
||||
* to be used. If BOM is not found then use a given default or system encoding.
|
||||
*/
|
||||
public class UnicodeReader extends Reader {
|
||||
private static final Charset UTF8 = Charset.forName("UTF-8");
|
||||
private static final Charset UTF16BE = Charset.forName("UTF-16BE");
|
||||
private static final Charset UTF16LE = Charset.forName("UTF-16LE");
|
||||
|
||||
PushbackInputStream internalIn;
|
||||
InputStreamReader internalIn2 = null;
|
||||
|
||||
private static final int BOM_SIZE = 3;
|
||||
|
||||
/**
|
||||
* @param in
|
||||
* InputStream to be read
|
||||
*/
|
||||
public UnicodeReader(InputStream in) {
|
||||
internalIn = new PushbackInputStream(in, BOM_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get stream encoding or NULL if stream is uninitialized. Call init() or
|
||||
* read() method to initialize it.
|
||||
* @return the name of the character encoding being used by this stream.
|
||||
*/
|
||||
public String getEncoding() {
|
||||
return internalIn2.getEncoding();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read-ahead four bytes and check for BOM marks. Extra bytes are unread
|
||||
* back to the stream, only BOM bytes are skipped.
|
||||
* @throws IOException if InputStream cannot be created
|
||||
*/
|
||||
protected void init() throws IOException {
|
||||
if (internalIn2 != null)
|
||||
return;
|
||||
|
||||
Charset encoding;
|
||||
byte bom[] = new byte[BOM_SIZE];
|
||||
int n, unread;
|
||||
n = internalIn.read(bom, 0, bom.length);
|
||||
|
||||
if ((bom[0] == (byte) 0xEF) && (bom[1] == (byte) 0xBB) && (bom[2] == (byte) 0xBF)) {
|
||||
encoding = UTF8;
|
||||
unread = n - 3;
|
||||
} else if ((bom[0] == (byte) 0xFE) && (bom[1] == (byte) 0xFF)) {
|
||||
encoding = UTF16BE;
|
||||
unread = n - 2;
|
||||
} else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)) {
|
||||
encoding = UTF16LE;
|
||||
unread = n - 2;
|
||||
} else {
|
||||
// Unicode BOM mark not found, unread all bytes
|
||||
encoding = UTF8;
|
||||
unread = n;
|
||||
}
|
||||
|
||||
if (unread > 0)
|
||||
internalIn.unread(bom, (n - unread), unread);
|
||||
|
||||
// Use given encoding
|
||||
CharsetDecoder decoder = encoding.newDecoder().onUnmappableCharacter(
|
||||
CodingErrorAction.REPORT);
|
||||
internalIn2 = new InputStreamReader(internalIn, decoder);
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
init();
|
||||
internalIn2.close();
|
||||
}
|
||||
|
||||
public int read(char[] cbuf, int off, int len) throws IOException {
|
||||
init();
|
||||
return internalIn2.read(cbuf, off, len);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,210 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.representer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.DumperOptions;
|
||||
import io.jenkins.plugins.casc.snakeyaml.DumperOptions.FlowStyle;
|
||||
import io.jenkins.plugins.casc.snakeyaml.DumperOptions.ScalarStyle;
|
||||
import io.jenkins.plugins.casc.snakeyaml.introspector.PropertyUtils;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.AnchorNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.MappingNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Node;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.NodeTuple;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.ScalarNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.SequenceNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Tag;
|
||||
|
||||
/**
|
||||
* Represent basic YAML structures: scalar, sequence, mapping
|
||||
*/
|
||||
public abstract class BaseRepresenter {
|
||||
protected final Map<Class<?>, Represent> representers = new HashMap<Class<?>, Represent>();
|
||||
/**
|
||||
* in Java 'null' is not a type. So we have to keep the null representer
|
||||
* separately otherwise it will coincide with the default representer which
|
||||
* is stored with the key null.
|
||||
*/
|
||||
protected Represent nullRepresenter;
|
||||
// the order is important (map can be also a sequence of key-values)
|
||||
protected final Map<Class<?>, Represent> multiRepresenters = new LinkedHashMap<Class<?>, Represent>();
|
||||
protected DumperOptions.ScalarStyle defaultScalarStyle = null; //not explicitly defined
|
||||
protected FlowStyle defaultFlowStyle = FlowStyle.AUTO;
|
||||
protected final Map<Object, Node> representedObjects = new IdentityHashMap<Object, Node>() {
|
||||
private static final long serialVersionUID = -5576159264232131854L;
|
||||
|
||||
public Node put(Object key, Node value) {
|
||||
return super.put(key, new AnchorNode(value));
|
||||
}
|
||||
};
|
||||
|
||||
protected Object objectToRepresent;
|
||||
private PropertyUtils propertyUtils;
|
||||
private boolean explicitPropertyUtils = false;
|
||||
|
||||
public Node represent(Object data) {
|
||||
Node node = representData(data);
|
||||
representedObjects.clear();
|
||||
objectToRepresent = null;
|
||||
return node;
|
||||
}
|
||||
|
||||
protected final Node representData(Object data) {
|
||||
objectToRepresent = data;
|
||||
// check for identity
|
||||
if (representedObjects.containsKey(objectToRepresent)) {
|
||||
Node node = representedObjects.get(objectToRepresent);
|
||||
return node;
|
||||
}
|
||||
// }
|
||||
// check for null first
|
||||
if (data == null) {
|
||||
Node node = nullRepresenter.representData(null);
|
||||
return node;
|
||||
}
|
||||
// check the same class
|
||||
Node node;
|
||||
Class<?> clazz = data.getClass();
|
||||
if (representers.containsKey(clazz)) {
|
||||
Represent representer = representers.get(clazz);
|
||||
node = representer.representData(data);
|
||||
} else {
|
||||
// check the parents
|
||||
for (Class<?> repr : multiRepresenters.keySet()) {
|
||||
if (repr != null && repr.isInstance(data)) {
|
||||
Represent representer = multiRepresenters.get(repr);
|
||||
node = representer.representData(data);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
// check defaults
|
||||
if (multiRepresenters.containsKey(null)) {
|
||||
Represent representer = multiRepresenters.get(null);
|
||||
node = representer.representData(data);
|
||||
} else {
|
||||
Represent representer = representers.get(null);
|
||||
node = representer.representData(data);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
protected Node representScalar(Tag tag, String value, DumperOptions.ScalarStyle style) {
|
||||
if (style == null) {
|
||||
style = this.defaultScalarStyle;
|
||||
}
|
||||
Node node = new ScalarNode(tag, value, null, null, style);
|
||||
return node;
|
||||
}
|
||||
|
||||
protected Node representScalar(Tag tag, String value) {
|
||||
return representScalar(tag, value, null);
|
||||
}
|
||||
|
||||
protected Node representSequence(Tag tag, Iterable<?> sequence, DumperOptions.FlowStyle flowStyle) {
|
||||
int size = 10;// default for ArrayList
|
||||
if (sequence instanceof List<?>) {
|
||||
size = ((List<?>) sequence).size();
|
||||
}
|
||||
List<Node> value = new ArrayList<Node>(size);
|
||||
SequenceNode node = new SequenceNode(tag, value, flowStyle);
|
||||
representedObjects.put(objectToRepresent, node);
|
||||
DumperOptions.FlowStyle bestStyle = FlowStyle.FLOW;
|
||||
for (Object item : sequence) {
|
||||
Node nodeItem = representData(item);
|
||||
if (!(nodeItem instanceof ScalarNode && ((ScalarNode) nodeItem).isPlain())) {
|
||||
bestStyle = FlowStyle.BLOCK;
|
||||
}
|
||||
value.add(nodeItem);
|
||||
}
|
||||
if (flowStyle == FlowStyle.AUTO) {
|
||||
if (defaultFlowStyle != FlowStyle.AUTO) {
|
||||
node.setFlowStyle(defaultFlowStyle);
|
||||
} else {
|
||||
node.setFlowStyle(bestStyle);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
protected Node representMapping(Tag tag, Map<?, ?> mapping, DumperOptions.FlowStyle flowStyle) {
|
||||
List<NodeTuple> value = new ArrayList<NodeTuple>(mapping.size());
|
||||
MappingNode node = new MappingNode(tag, value, flowStyle);
|
||||
representedObjects.put(objectToRepresent, node);
|
||||
DumperOptions.FlowStyle bestStyle = FlowStyle.FLOW;
|
||||
for (Map.Entry<?, ?> entry : mapping.entrySet()) {
|
||||
Node nodeKey = representData(entry.getKey());
|
||||
Node nodeValue = representData(entry.getValue());
|
||||
if (!(nodeKey instanceof ScalarNode && ((ScalarNode) nodeKey).isPlain())) {
|
||||
bestStyle = FlowStyle.BLOCK;
|
||||
}
|
||||
if (!(nodeValue instanceof ScalarNode && ((ScalarNode) nodeValue).isPlain())) {
|
||||
bestStyle = FlowStyle.BLOCK;
|
||||
}
|
||||
value.add(new NodeTuple(nodeKey, nodeValue));
|
||||
}
|
||||
if (flowStyle == FlowStyle.AUTO) {
|
||||
if (defaultFlowStyle != FlowStyle.AUTO) {
|
||||
node.setFlowStyle(defaultFlowStyle);
|
||||
} else {
|
||||
node.setFlowStyle(bestStyle);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
public void setDefaultScalarStyle(ScalarStyle defaultStyle) {
|
||||
this.defaultScalarStyle = defaultStyle;
|
||||
}
|
||||
|
||||
public ScalarStyle getDefaultScalarStyle() {
|
||||
if (defaultScalarStyle == null) {
|
||||
return ScalarStyle.PLAIN;
|
||||
}
|
||||
return defaultScalarStyle;
|
||||
}
|
||||
|
||||
public void setDefaultFlowStyle(FlowStyle defaultFlowStyle) {
|
||||
this.defaultFlowStyle = defaultFlowStyle;
|
||||
}
|
||||
|
||||
public FlowStyle getDefaultFlowStyle() {
|
||||
return this.defaultFlowStyle;
|
||||
}
|
||||
|
||||
public void setPropertyUtils(PropertyUtils propertyUtils) {
|
||||
this.propertyUtils = propertyUtils;
|
||||
this.explicitPropertyUtils = true;
|
||||
}
|
||||
|
||||
public final PropertyUtils getPropertyUtils() {
|
||||
if (propertyUtils == null) {
|
||||
propertyUtils = new PropertyUtils();
|
||||
}
|
||||
return propertyUtils;
|
||||
}
|
||||
|
||||
public final boolean isExplicitPropertyUtils() {
|
||||
return explicitPropertyUtils;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.representer;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Node;
|
||||
|
||||
/**
|
||||
* Create a Node Graph out of the provided Native Data Structure (Java
|
||||
* instance).
|
||||
*
|
||||
* @see <a href="http://yaml.org/spec/1.1/#id859109">Chapter 3. Processing YAML
|
||||
* Information</a>
|
||||
*/
|
||||
public interface Represent {
|
||||
/**
|
||||
* Create a Node
|
||||
*
|
||||
* @param data
|
||||
* the instance to represent
|
||||
* @return Node to dump
|
||||
*/
|
||||
Node representData(Object data);
|
||||
}
|
||||
|
|
@ -0,0 +1,275 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.representer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.DumperOptions;
|
||||
import io.jenkins.plugins.casc.snakeyaml.DumperOptions.FlowStyle;
|
||||
import io.jenkins.plugins.casc.snakeyaml.TypeDescription;
|
||||
import io.jenkins.plugins.casc.snakeyaml.introspector.Property;
|
||||
import io.jenkins.plugins.casc.snakeyaml.introspector.PropertyUtils;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.MappingNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Node;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.NodeId;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.NodeTuple;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.ScalarNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.SequenceNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Tag;
|
||||
|
||||
/**
|
||||
* Represent JavaBeans
|
||||
*/
|
||||
public class Representer extends SafeRepresenter {
|
||||
|
||||
protected Map<Class<? extends Object>, TypeDescription> typeDefinitions = Collections
|
||||
.emptyMap();
|
||||
|
||||
public Representer() {
|
||||
this.representers.put(null, new RepresentJavaBean());
|
||||
}
|
||||
|
||||
public TypeDescription addTypeDescription(TypeDescription td) {
|
||||
if (Collections.EMPTY_MAP == typeDefinitions) {
|
||||
typeDefinitions = new HashMap<Class<? extends Object>, TypeDescription>();
|
||||
}
|
||||
if (td.getTag() != null) {
|
||||
addClassTag(td.getType(), td.getTag());
|
||||
}
|
||||
td.setPropertyUtils(getPropertyUtils());
|
||||
return typeDefinitions.put(td.getType(), td);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPropertyUtils(PropertyUtils propertyUtils) {
|
||||
super.setPropertyUtils(propertyUtils);
|
||||
Collection<TypeDescription> tds = typeDefinitions.values();
|
||||
for (TypeDescription typeDescription : tds) {
|
||||
typeDescription.setPropertyUtils(propertyUtils);
|
||||
}
|
||||
}
|
||||
|
||||
protected class RepresentJavaBean implements Represent {
|
||||
public Node representData(Object data) {
|
||||
return representJavaBean(getProperties(data.getClass()), data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag logic:
|
||||
* - explicit root tag is set in serializer
|
||||
* - if there is a predefined class tag it is used
|
||||
* - a global tag with class name is always used as tag. The JavaBean parent
|
||||
* of the specified JavaBean may set another tag (tag:yaml.org,2002:map)
|
||||
* when the property class is the same as runtime class
|
||||
*
|
||||
* @param properties
|
||||
* JavaBean getters
|
||||
* @param javaBean
|
||||
* instance for Node
|
||||
* @return Node to get serialized
|
||||
*/
|
||||
protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
|
||||
List<NodeTuple> value = new ArrayList<NodeTuple>(properties.size());
|
||||
Tag tag;
|
||||
Tag customTag = classTags.get(javaBean.getClass());
|
||||
tag = customTag != null ? customTag : new Tag(javaBean.getClass());
|
||||
// flow style will be chosen by BaseRepresenter
|
||||
MappingNode node = new MappingNode(tag, value, FlowStyle.AUTO);
|
||||
representedObjects.put(javaBean, node);
|
||||
DumperOptions.FlowStyle bestStyle = FlowStyle.FLOW;
|
||||
for (Property property : properties) {
|
||||
Object memberValue = property.get(javaBean);
|
||||
Tag customPropertyTag = memberValue == null ? null
|
||||
: classTags.get(memberValue.getClass());
|
||||
NodeTuple tuple = representJavaBeanProperty(javaBean, property, memberValue,
|
||||
customPropertyTag);
|
||||
if (tuple == null) {
|
||||
continue;
|
||||
}
|
||||
if (!((ScalarNode) tuple.getKeyNode()).isPlain()) {
|
||||
bestStyle = FlowStyle.BLOCK;
|
||||
}
|
||||
Node nodeValue = tuple.getValueNode();
|
||||
if (!(nodeValue instanceof ScalarNode && ((ScalarNode) nodeValue).isPlain())) {
|
||||
bestStyle = FlowStyle.BLOCK;
|
||||
}
|
||||
value.add(tuple);
|
||||
}
|
||||
if (defaultFlowStyle != FlowStyle.AUTO) {
|
||||
node.setFlowStyle(defaultFlowStyle);
|
||||
} else {
|
||||
node.setFlowStyle(bestStyle);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represent one JavaBean property.
|
||||
*
|
||||
* @param javaBean
|
||||
* - the instance to be represented
|
||||
* @param property
|
||||
* - the property of the instance
|
||||
* @param propertyValue
|
||||
* - value to be represented
|
||||
* @param customTag
|
||||
* - user defined Tag
|
||||
* @return NodeTuple to be used in a MappingNode. Return null to skip the
|
||||
* property
|
||||
*/
|
||||
protected NodeTuple representJavaBeanProperty(Object javaBean, Property property,
|
||||
Object propertyValue, Tag customTag) {
|
||||
ScalarNode nodeKey = (ScalarNode) representData(property.getName());
|
||||
// the first occurrence of the node must keep the tag
|
||||
boolean hasAlias = this.representedObjects.containsKey(propertyValue);
|
||||
|
||||
Node nodeValue = representData(propertyValue);
|
||||
|
||||
if (propertyValue != null && !hasAlias) {
|
||||
NodeId nodeId = nodeValue.getNodeId();
|
||||
if (customTag == null) {
|
||||
if (nodeId == NodeId.scalar) {
|
||||
//generic Enum requires the full tag
|
||||
if (property.getType() != java.lang.Enum.class) {
|
||||
if (propertyValue instanceof Enum<?>) {
|
||||
nodeValue.setTag(Tag.STR);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (nodeId == NodeId.mapping) {
|
||||
if (property.getType() == propertyValue.getClass()) {
|
||||
if (!(propertyValue instanceof Map<?, ?>)) {
|
||||
if (!nodeValue.getTag().equals(Tag.SET)) {
|
||||
nodeValue.setTag(Tag.MAP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
checkGlobalTag(property, nodeValue, propertyValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new NodeTuple(nodeKey, nodeValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove redundant global tag for a type safe (generic) collection if it is
|
||||
* the same as defined by the JavaBean property
|
||||
*
|
||||
* @param property
|
||||
* - JavaBean property
|
||||
* @param node
|
||||
* - representation of the property
|
||||
* @param object
|
||||
* - instance represented by the node
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void checkGlobalTag(Property property, Node node, Object object) {
|
||||
// Skip primitive arrays.
|
||||
if (object.getClass().isArray() && object.getClass().getComponentType().isPrimitive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Class<?>[] arguments = property.getActualTypeArguments();
|
||||
if (arguments != null) {
|
||||
if (node.getNodeId() == NodeId.sequence) {
|
||||
// apply map tag where class is the same
|
||||
Class<? extends Object> t = arguments[0];
|
||||
SequenceNode snode = (SequenceNode) node;
|
||||
Iterable<Object> memberList = Collections.EMPTY_LIST;
|
||||
if (object.getClass().isArray()) {
|
||||
memberList = Arrays.asList((Object[]) object);
|
||||
} else if (object instanceof Iterable<?>) {
|
||||
// list
|
||||
memberList = (Iterable<Object>) object;
|
||||
}
|
||||
Iterator<Object> iter = memberList.iterator();
|
||||
if (iter.hasNext()) {
|
||||
for (Node childNode : snode.getValue()) {
|
||||
Object member = iter.next();
|
||||
if (member != null) {
|
||||
if (t.equals(member.getClass()))
|
||||
if (childNode.getNodeId() == NodeId.mapping) {
|
||||
childNode.setTag(Tag.MAP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (object instanceof Set) {
|
||||
Class<?> t = arguments[0];
|
||||
MappingNode mnode = (MappingNode) node;
|
||||
Iterator<NodeTuple> iter = mnode.getValue().iterator();
|
||||
Set<?> set = (Set<?>) object;
|
||||
for (Object member : set) {
|
||||
NodeTuple tuple = iter.next();
|
||||
Node keyNode = tuple.getKeyNode();
|
||||
if (t.equals(member.getClass())) {
|
||||
if (keyNode.getNodeId() == NodeId.mapping) {
|
||||
keyNode.setTag(Tag.MAP);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (object instanceof Map) { // NodeId.mapping ends-up here
|
||||
Class<?> keyType = arguments[0];
|
||||
Class<?> valueType = arguments[1];
|
||||
MappingNode mnode = (MappingNode) node;
|
||||
for (NodeTuple tuple : mnode.getValue()) {
|
||||
resetTag(keyType, tuple.getKeyNode());
|
||||
resetTag(valueType, tuple.getValueNode());
|
||||
}
|
||||
} else {
|
||||
// the type for collection entries cannot be
|
||||
// detected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resetTag(Class<? extends Object> type, Node node) {
|
||||
Tag tag = node.getTag();
|
||||
if (tag.matches(type)) {
|
||||
if (Enum.class.isAssignableFrom(type)) {
|
||||
node.setTag(Tag.STR);
|
||||
} else {
|
||||
node.setTag(Tag.MAP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get JavaBean properties to be serialised. The order is respected. This
|
||||
* method may be overridden to provide custom property selection or order.
|
||||
*
|
||||
* @param type
|
||||
* - JavaBean to inspect the properties
|
||||
* @return properties to serialise
|
||||
*/
|
||||
protected Set<Property> getProperties(Class<? extends Object> type) {
|
||||
if (typeDefinitions.containsKey(type)) {
|
||||
return typeDefinitions.get(type).getProperties();
|
||||
}
|
||||
return getPropertyUtils().getProperties(type);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,451 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.representer;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.DumperOptions;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.YAMLException;
|
||||
import io.jenkins.plugins.casc.snakeyaml.external.biz.base64Coder.Base64Coder;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Node;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Tag;
|
||||
import io.jenkins.plugins.casc.snakeyaml.reader.StreamReader;
|
||||
|
||||
/**
|
||||
* Represent standard Java classes
|
||||
*/
|
||||
class SafeRepresenter extends BaseRepresenter {
|
||||
|
||||
protected Map<Class<? extends Object>, Tag> classTags;
|
||||
protected TimeZone timeZone = null;
|
||||
|
||||
public SafeRepresenter() {
|
||||
this.nullRepresenter = new RepresentNull();
|
||||
this.representers.put(String.class, new RepresentString());
|
||||
this.representers.put(Boolean.class, new RepresentBoolean());
|
||||
this.representers.put(Character.class, new RepresentString());
|
||||
this.representers.put(UUID.class, new RepresentUuid());
|
||||
this.representers.put(byte[].class, new RepresentByteArray());
|
||||
|
||||
Represent primitiveArray = new RepresentPrimitiveArray();
|
||||
representers.put(short[].class, primitiveArray);
|
||||
representers.put(int[].class, primitiveArray);
|
||||
representers.put(long[].class, primitiveArray);
|
||||
representers.put(float[].class, primitiveArray);
|
||||
representers.put(double[].class, primitiveArray);
|
||||
representers.put(char[].class, primitiveArray);
|
||||
representers.put(boolean[].class, primitiveArray);
|
||||
|
||||
this.multiRepresenters.put(Number.class, new RepresentNumber());
|
||||
this.multiRepresenters.put(List.class, new RepresentList());
|
||||
this.multiRepresenters.put(Map.class, new RepresentMap());
|
||||
this.multiRepresenters.put(Set.class, new RepresentSet());
|
||||
this.multiRepresenters.put(Iterator.class, new RepresentIterator());
|
||||
this.multiRepresenters.put(new Object[0].getClass(), new RepresentArray());
|
||||
this.multiRepresenters.put(Date.class, new RepresentDate());
|
||||
this.multiRepresenters.put(Enum.class, new RepresentEnum());
|
||||
this.multiRepresenters.put(Calendar.class, new RepresentDate());
|
||||
classTags = new HashMap<Class<? extends Object>, Tag>();
|
||||
}
|
||||
|
||||
protected Tag getTag(Class<?> clazz, Tag defaultTag) {
|
||||
if (classTags.containsKey(clazz)) {
|
||||
return classTags.get(clazz);
|
||||
} else {
|
||||
return defaultTag;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a tag for the <code>Class</code> to serialize.
|
||||
*
|
||||
* @param clazz
|
||||
* <code>Class</code> which tag is changed
|
||||
* @param tag
|
||||
* new tag to be used for every instance of the specified
|
||||
* <code>Class</code>
|
||||
* @return the previous tag associated with the <code>Class</code>
|
||||
*/
|
||||
public Tag addClassTag(Class<? extends Object> clazz, Tag tag) {
|
||||
if (tag == null) {
|
||||
throw new NullPointerException("Tag must be provided.");
|
||||
}
|
||||
return classTags.put(clazz, tag);
|
||||
}
|
||||
|
||||
protected class RepresentNull implements Represent {
|
||||
public Node representData(Object data) {
|
||||
return representScalar(Tag.NULL, "null");
|
||||
}
|
||||
}
|
||||
|
||||
public static Pattern MULTILINE_PATTERN = Pattern.compile("\n|\u0085|\u2028|\u2029");
|
||||
|
||||
protected class RepresentString implements Represent {
|
||||
public Node representData(Object data) {
|
||||
Tag tag = Tag.STR;
|
||||
DumperOptions.ScalarStyle style = null;//not defined
|
||||
String value = data.toString();
|
||||
if (!StreamReader.isPrintable(value)) {
|
||||
tag = Tag.BINARY;
|
||||
char[] binary;
|
||||
try {
|
||||
final byte[] bytes = value.getBytes("UTF-8");
|
||||
// sometimes above will just silently fail - it will return incomplete data
|
||||
// it happens when String has invalid code points
|
||||
// (for example half surrogate character without other half)
|
||||
final String checkValue = new String(bytes, "UTF-8");
|
||||
if (!checkValue.equals(value)) {
|
||||
throw new YAMLException("invalid string value has occurred");
|
||||
}
|
||||
binary = Base64Coder.encode(bytes);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new YAMLException(e);
|
||||
}
|
||||
value = String.valueOf(binary);
|
||||
style = DumperOptions.ScalarStyle.LITERAL;
|
||||
}
|
||||
// if no other scalar style is explicitly set, use literal style for
|
||||
// multiline scalars
|
||||
if (defaultScalarStyle == DumperOptions.ScalarStyle.PLAIN && MULTILINE_PATTERN.matcher(value).find()) {
|
||||
style = DumperOptions.ScalarStyle.LITERAL;
|
||||
}
|
||||
return representScalar(tag, value, style);
|
||||
}
|
||||
}
|
||||
|
||||
protected class RepresentBoolean implements Represent {
|
||||
public Node representData(Object data) {
|
||||
String value;
|
||||
if (Boolean.TRUE.equals(data)) {
|
||||
value = "true";
|
||||
} else {
|
||||
value = "false";
|
||||
}
|
||||
return representScalar(Tag.BOOL, value);
|
||||
}
|
||||
}
|
||||
|
||||
protected class RepresentNumber implements Represent {
|
||||
public Node representData(Object data) {
|
||||
Tag tag;
|
||||
String value;
|
||||
if (data instanceof Byte || data instanceof Short || data instanceof Integer
|
||||
|| data instanceof Long || data instanceof BigInteger) {
|
||||
tag = Tag.INT;
|
||||
value = data.toString();
|
||||
} else {
|
||||
Number number = (Number) data;
|
||||
tag = Tag.FLOAT;
|
||||
if (number.equals(Double.NaN)) {
|
||||
value = ".NaN";
|
||||
} else if (number.equals(Double.POSITIVE_INFINITY)) {
|
||||
value = ".inf";
|
||||
} else if (number.equals(Double.NEGATIVE_INFINITY)) {
|
||||
value = "-.inf";
|
||||
} else {
|
||||
value = number.toString();
|
||||
}
|
||||
}
|
||||
return representScalar(getTag(data.getClass(), tag), value);
|
||||
}
|
||||
}
|
||||
|
||||
protected class RepresentList implements Represent {
|
||||
@SuppressWarnings("unchecked")
|
||||
public Node representData(Object data) {
|
||||
return representSequence(getTag(data.getClass(), Tag.SEQ), (List<Object>) data, DumperOptions.FlowStyle.AUTO);
|
||||
}
|
||||
}
|
||||
|
||||
protected class RepresentIterator implements Represent {
|
||||
@SuppressWarnings("unchecked")
|
||||
public Node representData(Object data) {
|
||||
Iterator<Object> iter = (Iterator<Object>) data;
|
||||
return representSequence(getTag(data.getClass(), Tag.SEQ), new IteratorWrapper(iter),
|
||||
DumperOptions.FlowStyle.AUTO);
|
||||
}
|
||||
}
|
||||
|
||||
private static class IteratorWrapper implements Iterable<Object> {
|
||||
private Iterator<Object> iter;
|
||||
|
||||
public IteratorWrapper(Iterator<Object> iter) {
|
||||
this.iter = iter;
|
||||
}
|
||||
|
||||
public Iterator<Object> iterator() {
|
||||
return iter;
|
||||
}
|
||||
}
|
||||
|
||||
protected class RepresentArray implements Represent {
|
||||
public Node representData(Object data) {
|
||||
Object[] array = (Object[]) data;
|
||||
List<Object> list = Arrays.asList(array);
|
||||
return representSequence(Tag.SEQ, list, DumperOptions.FlowStyle.AUTO);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents primitive arrays, such as short[] and float[], by converting
|
||||
* them into equivalent List<Short> and List<Float> using the appropriate
|
||||
* autoboxing type.
|
||||
*/
|
||||
protected class RepresentPrimitiveArray implements Represent {
|
||||
public Node representData(Object data) {
|
||||
Class<?> type = data.getClass().getComponentType();
|
||||
|
||||
if (byte.class == type) {
|
||||
return representSequence(Tag.SEQ, asByteList(data), DumperOptions.FlowStyle.AUTO);
|
||||
} else if (short.class == type) {
|
||||
return representSequence(Tag.SEQ, asShortList(data), DumperOptions.FlowStyle.AUTO);
|
||||
} else if (int.class == type) {
|
||||
return representSequence(Tag.SEQ, asIntList(data), DumperOptions.FlowStyle.AUTO);
|
||||
} else if (long.class == type) {
|
||||
return representSequence(Tag.SEQ, asLongList(data), DumperOptions.FlowStyle.AUTO);
|
||||
} else if (float.class == type) {
|
||||
return representSequence(Tag.SEQ, asFloatList(data), DumperOptions.FlowStyle.AUTO);
|
||||
} else if (double.class == type) {
|
||||
return representSequence(Tag.SEQ, asDoubleList(data), DumperOptions.FlowStyle.AUTO);
|
||||
} else if (char.class == type) {
|
||||
return representSequence(Tag.SEQ, asCharList(data), DumperOptions.FlowStyle.AUTO);
|
||||
} else if (boolean.class == type) {
|
||||
return representSequence(Tag.SEQ, asBooleanList(data), DumperOptions.FlowStyle.AUTO);
|
||||
}
|
||||
|
||||
throw new YAMLException("Unexpected primitive '" + type.getCanonicalName() + "'");
|
||||
}
|
||||
|
||||
private List<Byte> asByteList(Object in) {
|
||||
byte[] array = (byte[]) in;
|
||||
List<Byte> list = new ArrayList<Byte>(array.length);
|
||||
for (int i = 0; i < array.length; ++i)
|
||||
list.add(array[i]);
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<Short> asShortList(Object in) {
|
||||
short[] array = (short[]) in;
|
||||
List<Short> list = new ArrayList<Short>(array.length);
|
||||
for (int i = 0; i < array.length; ++i)
|
||||
list.add(array[i]);
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<Integer> asIntList(Object in) {
|
||||
int[] array = (int[]) in;
|
||||
List<Integer> list = new ArrayList<Integer>(array.length);
|
||||
for (int i = 0; i < array.length; ++i)
|
||||
list.add(array[i]);
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<Long> asLongList(Object in) {
|
||||
long[] array = (long[]) in;
|
||||
List<Long> list = new ArrayList<Long>(array.length);
|
||||
for (int i = 0; i < array.length; ++i)
|
||||
list.add(array[i]);
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<Float> asFloatList(Object in) {
|
||||
float[] array = (float[]) in;
|
||||
List<Float> list = new ArrayList<Float>(array.length);
|
||||
for (int i = 0; i < array.length; ++i)
|
||||
list.add(array[i]);
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<Double> asDoubleList(Object in) {
|
||||
double[] array = (double[]) in;
|
||||
List<Double> list = new ArrayList<Double>(array.length);
|
||||
for (int i = 0; i < array.length; ++i)
|
||||
list.add(array[i]);
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<Character> asCharList(Object in) {
|
||||
char[] array = (char[]) in;
|
||||
List<Character> list = new ArrayList<Character>(array.length);
|
||||
for (int i = 0; i < array.length; ++i)
|
||||
list.add(array[i]);
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<Boolean> asBooleanList(Object in) {
|
||||
boolean[] array = (boolean[]) in;
|
||||
List<Boolean> list = new ArrayList<Boolean>(array.length);
|
||||
for (int i = 0; i < array.length; ++i)
|
||||
list.add(array[i]);
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
protected class RepresentMap implements Represent {
|
||||
@SuppressWarnings("unchecked")
|
||||
public Node representData(Object data) {
|
||||
return representMapping(getTag(data.getClass(), Tag.MAP), (Map<Object, Object>) data,
|
||||
DumperOptions.FlowStyle.AUTO);
|
||||
}
|
||||
}
|
||||
|
||||
protected class RepresentSet implements Represent {
|
||||
@SuppressWarnings("unchecked")
|
||||
public Node representData(Object data) {
|
||||
Map<Object, Object> value = new LinkedHashMap<Object, Object>();
|
||||
Set<Object> set = (Set<Object>) data;
|
||||
for (Object key : set) {
|
||||
value.put(key, null);
|
||||
}
|
||||
return representMapping(getTag(data.getClass(), Tag.SET), value, DumperOptions.FlowStyle.AUTO);
|
||||
}
|
||||
}
|
||||
|
||||
protected class RepresentDate implements Represent {
|
||||
public Node representData(Object data) {
|
||||
// because SimpleDateFormat ignores timezone we have to use Calendar
|
||||
Calendar calendar;
|
||||
if (data instanceof Calendar) {
|
||||
calendar = (Calendar) data;
|
||||
} else {
|
||||
calendar = Calendar.getInstance(getTimeZone() == null ? TimeZone.getTimeZone("UTC")
|
||||
: timeZone);
|
||||
calendar.setTime((Date) data);
|
||||
}
|
||||
int years = calendar.get(Calendar.YEAR);
|
||||
int months = calendar.get(Calendar.MONTH) + 1; // 0..12
|
||||
int days = calendar.get(Calendar.DAY_OF_MONTH); // 1..31
|
||||
int hour24 = calendar.get(Calendar.HOUR_OF_DAY); // 0..24
|
||||
int minutes = calendar.get(Calendar.MINUTE); // 0..59
|
||||
int seconds = calendar.get(Calendar.SECOND); // 0..59
|
||||
int millis = calendar.get(Calendar.MILLISECOND);
|
||||
StringBuilder buffer = new StringBuilder(String.valueOf(years));
|
||||
while (buffer.length() < 4) {
|
||||
// ancient years
|
||||
buffer.insert(0, "0");
|
||||
}
|
||||
buffer.append("-");
|
||||
if (months < 10) {
|
||||
buffer.append("0");
|
||||
}
|
||||
buffer.append(String.valueOf(months));
|
||||
buffer.append("-");
|
||||
if (days < 10) {
|
||||
buffer.append("0");
|
||||
}
|
||||
buffer.append(String.valueOf(days));
|
||||
buffer.append("T");
|
||||
if (hour24 < 10) {
|
||||
buffer.append("0");
|
||||
}
|
||||
buffer.append(String.valueOf(hour24));
|
||||
buffer.append(":");
|
||||
if (minutes < 10) {
|
||||
buffer.append("0");
|
||||
}
|
||||
buffer.append(String.valueOf(minutes));
|
||||
buffer.append(":");
|
||||
if (seconds < 10) {
|
||||
buffer.append("0");
|
||||
}
|
||||
buffer.append(String.valueOf(seconds));
|
||||
if (millis > 0) {
|
||||
if (millis < 10) {
|
||||
buffer.append(".00");
|
||||
} else if (millis < 100) {
|
||||
buffer.append(".0");
|
||||
} else {
|
||||
buffer.append(".");
|
||||
}
|
||||
buffer.append(String.valueOf(millis));
|
||||
}
|
||||
|
||||
// Get the offset from GMT taking DST into account
|
||||
int gmtOffset = calendar.getTimeZone().getOffset(calendar.get(Calendar.ERA),
|
||||
calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
|
||||
calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.DAY_OF_WEEK),
|
||||
calendar.get(Calendar.MILLISECOND));
|
||||
if (gmtOffset == 0) {
|
||||
buffer.append('Z');
|
||||
} else {
|
||||
if (gmtOffset < 0) {
|
||||
buffer.append('-');
|
||||
gmtOffset *= -1;
|
||||
} else {
|
||||
buffer.append('+');
|
||||
}
|
||||
int minutesOffset = gmtOffset / (60 * 1000);
|
||||
int hoursOffset = minutesOffset / 60;
|
||||
int partOfHour = minutesOffset % 60;
|
||||
|
||||
if (hoursOffset < 10) {
|
||||
buffer.append('0');
|
||||
}
|
||||
buffer.append(hoursOffset);
|
||||
buffer.append(':');
|
||||
if (partOfHour < 10) {
|
||||
buffer.append('0');
|
||||
}
|
||||
buffer.append(partOfHour);
|
||||
}
|
||||
|
||||
return representScalar(getTag(data.getClass(), Tag.TIMESTAMP), buffer.toString(), DumperOptions.ScalarStyle.PLAIN);
|
||||
}
|
||||
}
|
||||
|
||||
protected class RepresentEnum implements Represent {
|
||||
public Node representData(Object data) {
|
||||
Tag tag = new Tag(data.getClass());
|
||||
return representScalar(getTag(data.getClass(), tag), ((Enum<?>) data).name());
|
||||
}
|
||||
}
|
||||
|
||||
protected class RepresentByteArray implements Represent {
|
||||
public Node representData(Object data) {
|
||||
char[] binary = Base64Coder.encode((byte[]) data);
|
||||
return representScalar(Tag.BINARY, String.valueOf(binary), DumperOptions.ScalarStyle.LITERAL);
|
||||
}
|
||||
}
|
||||
|
||||
public TimeZone getTimeZone() {
|
||||
return timeZone;
|
||||
}
|
||||
|
||||
public void setTimeZone(TimeZone timeZone) {
|
||||
this.timeZone = timeZone;
|
||||
}
|
||||
|
||||
protected class RepresentUuid implements Represent {
|
||||
public Node representData(Object data) {
|
||||
return representScalar(getTag(data.getClass(), new Tag(UUID.class)), data.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.resolver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.NodeId;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Tag;
|
||||
|
||||
/**
|
||||
* Resolver tries to detect a type by content (when the tag is implicit)
|
||||
*/
|
||||
public class Resolver {
|
||||
public static final Pattern BOOL = Pattern
|
||||
.compile("^(?:yes|Yes|YES|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF)$");
|
||||
|
||||
/**
|
||||
* The regular expression is taken from the 1.2 specification but '_'s are
|
||||
* added to keep backwards compatibility
|
||||
*/
|
||||
public static final Pattern FLOAT = Pattern
|
||||
.compile("^([-+]?(\\.[0-9]+|[0-9_]+(\\.[0-9_]*)?)([eE][-+]?[0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");
|
||||
public static final Pattern INT = Pattern
|
||||
.compile("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?(?:0|[1-9][0-9_]*)|[-+]?0x[0-9a-fA-F_]+|[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$");
|
||||
public static final Pattern MERGE = Pattern.compile("^(?:<<)$");
|
||||
public static final Pattern NULL = Pattern.compile("^(?:~|null|Null|NULL| )$");
|
||||
public static final Pattern EMPTY = Pattern.compile("^$");
|
||||
public static final Pattern TIMESTAMP = Pattern
|
||||
.compile("^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]|[0-9][0-9][0-9][0-9]-[0-9][0-9]?-[0-9][0-9]?(?:[Tt]|[ \t]+)[0-9][0-9]?:[0-9][0-9]:[0-9][0-9](?:\\.[0-9]*)?(?:[ \t]*(?:Z|[-+][0-9][0-9]?(?::[0-9][0-9])?))?)$");
|
||||
public static final Pattern VALUE = Pattern.compile("^(?:=)$");
|
||||
public static final Pattern YAML = Pattern.compile("^(?:!|&|\\*)$");
|
||||
|
||||
protected Map<Character, List<ResolverTuple>> yamlImplicitResolvers = new HashMap<Character, List<ResolverTuple>>();
|
||||
|
||||
protected void addImplicitResolvers() {
|
||||
addImplicitResolver(Tag.BOOL, BOOL, "yYnNtTfFoO");
|
||||
/*
|
||||
* INT must be before FLOAT because the regular expression for FLOAT
|
||||
* matches INT (see issue 130)
|
||||
* http://code.google.com/p/snakeyaml/issues/detail?id=130
|
||||
*/
|
||||
addImplicitResolver(Tag.INT, INT, "-+0123456789");
|
||||
addImplicitResolver(Tag.FLOAT, FLOAT, "-+0123456789.");
|
||||
addImplicitResolver(Tag.MERGE, MERGE, "<");
|
||||
addImplicitResolver(Tag.NULL, NULL, "~nN\0");
|
||||
addImplicitResolver(Tag.NULL, EMPTY, null);
|
||||
addImplicitResolver(Tag.TIMESTAMP, TIMESTAMP, "0123456789");
|
||||
// The following implicit resolver is only for documentation
|
||||
// purposes.
|
||||
// It cannot work
|
||||
// because plain scalars cannot start with '!', '&', or '*'.
|
||||
addImplicitResolver(Tag.YAML, YAML, "!&*");
|
||||
}
|
||||
|
||||
public Resolver() {
|
||||
addImplicitResolvers();
|
||||
}
|
||||
|
||||
public void addImplicitResolver(Tag tag, Pattern regexp, String first) {
|
||||
if (first == null) {
|
||||
List<ResolverTuple> curr = yamlImplicitResolvers.get(null);
|
||||
if (curr == null) {
|
||||
curr = new ArrayList<ResolverTuple>();
|
||||
yamlImplicitResolvers.put(null, curr);
|
||||
}
|
||||
curr.add(new ResolverTuple(tag, regexp));
|
||||
} else {
|
||||
char[] chrs = first.toCharArray();
|
||||
for (int i = 0, j = chrs.length; i < j; i++) {
|
||||
Character theC = Character.valueOf(chrs[i]);
|
||||
if (theC == 0) {
|
||||
// special case: for null
|
||||
theC = null;
|
||||
}
|
||||
List<ResolverTuple> curr = yamlImplicitResolvers.get(theC);
|
||||
if (curr == null) {
|
||||
curr = new ArrayList<ResolverTuple>();
|
||||
yamlImplicitResolvers.put(theC, curr);
|
||||
}
|
||||
curr.add(new ResolverTuple(tag, regexp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Tag resolve(NodeId kind, String value, boolean implicit) {
|
||||
if (kind == NodeId.scalar && implicit) {
|
||||
final List<ResolverTuple> resolvers;
|
||||
if (value.length() == 0) {
|
||||
resolvers = yamlImplicitResolvers.get('\0');
|
||||
} else {
|
||||
resolvers = yamlImplicitResolvers.get(value.charAt(0));
|
||||
}
|
||||
if (resolvers != null) {
|
||||
for (ResolverTuple v : resolvers) {
|
||||
Tag tag = v.getTag();
|
||||
Pattern regexp = v.getRegexp();
|
||||
if (regexp.matcher(value).matches()) {
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (yamlImplicitResolvers.containsKey(null)) {
|
||||
for (ResolverTuple v : yamlImplicitResolvers.get(null)) {
|
||||
Tag tag = v.getTag();
|
||||
Pattern regexp = v.getRegexp();
|
||||
if (regexp.matcher(value).matches()) {
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (kind) {
|
||||
case scalar:
|
||||
return Tag.STR;
|
||||
case sequence:
|
||||
return Tag.SEQ;
|
||||
default:
|
||||
return Tag.MAP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.resolver;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Tag;
|
||||
|
||||
final class ResolverTuple {
|
||||
private final Tag tag;
|
||||
private final Pattern regexp;
|
||||
|
||||
public ResolverTuple(Tag tag, Pattern regexp) {
|
||||
this.tag = tag;
|
||||
this.regexp = regexp;
|
||||
}
|
||||
|
||||
public Tag getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public Pattern getRegexp() {
|
||||
return regexp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Tuple tag=" + tag + " regexp=" + regexp;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.scanner;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class Constant {
|
||||
private final static String ALPHA_S = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
|
||||
|
||||
private final static String LINEBR_S = "\n\u0085\u2028\u2029";
|
||||
private final static String FULL_LINEBR_S = "\r" + LINEBR_S;
|
||||
private final static String NULL_OR_LINEBR_S = "\0" + FULL_LINEBR_S;
|
||||
private final static String NULL_BL_LINEBR_S = " " + NULL_OR_LINEBR_S;
|
||||
private final static String NULL_BL_T_LINEBR_S = "\t" + NULL_BL_LINEBR_S;
|
||||
private final static String NULL_BL_T_S = "\0 \t";
|
||||
private final static String URI_CHARS_S = ALPHA_S + "-;/?:@&=+$,_.!~*\'()[]%";
|
||||
|
||||
public final static Constant LINEBR = new Constant(LINEBR_S);
|
||||
public final static Constant FULL_LINEBR = new Constant(FULL_LINEBR_S);
|
||||
public final static Constant NULL_OR_LINEBR = new Constant(NULL_OR_LINEBR_S);
|
||||
public final static Constant NULL_BL_LINEBR = new Constant(NULL_BL_LINEBR_S);
|
||||
public final static Constant NULL_BL_T_LINEBR = new Constant(NULL_BL_T_LINEBR_S);
|
||||
public final static Constant NULL_BL_T = new Constant(NULL_BL_T_S);
|
||||
public final static Constant URI_CHARS = new Constant(URI_CHARS_S);
|
||||
|
||||
public final static Constant ALPHA = new Constant(ALPHA_S);
|
||||
|
||||
private String content;
|
||||
boolean[] contains = new boolean[128];
|
||||
boolean noASCII = false;
|
||||
|
||||
private Constant(String content) {
|
||||
Arrays.fill(contains, false);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < content.length(); i++) {
|
||||
int c = content.codePointAt(i);
|
||||
if (c < 128)
|
||||
contains[c] = true;
|
||||
else
|
||||
sb.appendCodePoint(c);
|
||||
}
|
||||
if (sb.length() > 0) {
|
||||
noASCII = true;
|
||||
this.content = sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean has(int c) {
|
||||
return (c < 128) ? contains[c] : noASCII && content.indexOf(c, 0) != -1;
|
||||
}
|
||||
|
||||
public boolean hasNo(int c) {
|
||||
return !has(c);
|
||||
}
|
||||
|
||||
public boolean has(int c, String additional) {
|
||||
return has(c) || additional.indexOf(c, 0) != -1;
|
||||
}
|
||||
|
||||
public boolean hasNo(int c, String additional) {
|
||||
return !has(c, additional);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.scanner;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.tokens.Token;
|
||||
|
||||
/**
|
||||
* This interface represents an input stream of {@link Token}s.
|
||||
* <p>
|
||||
* The parser and the scanner form together the 'Parse' step in the loading
|
||||
* process (see chapter 3.1 of the <a href="http://yaml.org/spec/1.1/">YAML
|
||||
* Specification</a>).
|
||||
* </p>
|
||||
*
|
||||
* @see io.jenkins.plugins.casc.snakeyaml.tokens.Token
|
||||
*/
|
||||
public interface Scanner {
|
||||
|
||||
/**
|
||||
* Check if the next token is one of the given types.
|
||||
*
|
||||
* @param choices
|
||||
* token IDs.
|
||||
* @return <code>true</code> if the next token can be assigned to a variable
|
||||
* of at least one of the given types. Returns <code>false</code> if
|
||||
* no more tokens are available.
|
||||
* @throws ScannerException
|
||||
* Thrown in case of malformed input.
|
||||
*/
|
||||
boolean checkToken(Token.ID... choices);
|
||||
|
||||
/**
|
||||
* Return the next token, but do not delete it from the stream.
|
||||
* The method must be called only after {@link #checkToken}.
|
||||
*
|
||||
* @return The token that will be returned on the next call to {@link #getToken}
|
||||
* @throws ScannerException Thrown in case of malformed input.
|
||||
* @throws IndexOutOfBoundsException if no more token left
|
||||
*/
|
||||
Token peekToken();
|
||||
|
||||
/**
|
||||
* Returns the next token.
|
||||
* <p>
|
||||
* The token will be removed from the stream.
|
||||
* (Every invocation of this method must happen after calling {@link #checkToken}.
|
||||
* </p>
|
||||
*
|
||||
* @return the coming token
|
||||
* @throws ScannerException Thrown in case of malformed input.
|
||||
* @throws IndexOutOfBoundsException if no more token left
|
||||
*/
|
||||
Token getToken();
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.scanner;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.MarkedYAMLException;
|
||||
|
||||
/**
|
||||
* Exception thrown by the {@link Scanner} implementations in case of malformed
|
||||
* input.
|
||||
*/
|
||||
public class ScannerException extends MarkedYAMLException {
|
||||
|
||||
private static final long serialVersionUID = 4782293188600445954L;
|
||||
|
||||
/**
|
||||
* Constructs an instance.
|
||||
*
|
||||
* @param context
|
||||
* Part of the input document in which vicinity the problem
|
||||
* occurred.
|
||||
* @param contextMark
|
||||
* Position of the <code>context</code> within the document.
|
||||
* @param problem
|
||||
* Part of the input document that caused the problem.
|
||||
* @param problemMark
|
||||
* Position of the <code>problem</code> within the document.
|
||||
* @param note
|
||||
* Message for the user with further information about the
|
||||
* problem.
|
||||
*/
|
||||
public ScannerException(String context, Mark contextMark, String problem, Mark problemMark,
|
||||
String note) {
|
||||
super(context, contextMark, problem, problemMark, note);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance.
|
||||
*
|
||||
* @param context
|
||||
* Part of the input document in which vicinity the problem
|
||||
* occurred.
|
||||
* @param contextMark
|
||||
* Position of the <code>context</code> within the document.
|
||||
* @param problem
|
||||
* Part of the input document that caused the problem.
|
||||
* @param problemMark
|
||||
* Position of the <code>problem</code> within the document.
|
||||
*/
|
||||
public ScannerException(String context, Mark contextMark, String problem, Mark problemMark) {
|
||||
this(context, contextMark, problem, problemMark, null);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.scanner;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
/**
|
||||
* Simple keys treatment.
|
||||
* <p>
|
||||
* Helper class for {@link ScannerImpl}.
|
||||
* </p>
|
||||
*
|
||||
* @see ScannerImpl
|
||||
*/
|
||||
final class SimpleKey {
|
||||
private int tokenNumber;
|
||||
private boolean required;
|
||||
private int index;
|
||||
private int line;
|
||||
private int column;
|
||||
private Mark mark;
|
||||
|
||||
public SimpleKey(int tokenNumber, boolean required, int index, int line, int column, Mark mark) {
|
||||
this.tokenNumber = tokenNumber;
|
||||
this.required = required;
|
||||
this.index = index;
|
||||
this.line = line;
|
||||
this.column = column;
|
||||
this.mark = mark;
|
||||
}
|
||||
|
||||
public int getTokenNumber() {
|
||||
return this.tokenNumber;
|
||||
}
|
||||
|
||||
public int getColumn() {
|
||||
return this.column;
|
||||
}
|
||||
|
||||
public Mark getMark() {
|
||||
return mark;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
|
||||
public boolean isRequired() {
|
||||
return required;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SimpleKey - tokenNumber=" + tokenNumber + " required=" + required + " index="
|
||||
+ index + " line=" + line + " column=" + column;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.serializer;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Node;
|
||||
|
||||
public interface AnchorGenerator {
|
||||
|
||||
String nextAnchor(Node node);
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.serializer;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Node;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
|
||||
public class NumberAnchorGenerator implements AnchorGenerator {
|
||||
|
||||
private int lastAnchorId = 0;
|
||||
|
||||
public NumberAnchorGenerator(int lastAnchorId) {
|
||||
this.lastAnchorId = lastAnchorId;
|
||||
}
|
||||
|
||||
public String nextAnchor(Node node) {
|
||||
this.lastAnchorId++;
|
||||
NumberFormat format = NumberFormat.getNumberInstance();
|
||||
format.setMinimumIntegerDigits(3);
|
||||
format.setMaximumFractionDigits(0);// issue 172
|
||||
format.setGroupingUsed(false);
|
||||
String anchorId = format.format(this.lastAnchorId);
|
||||
return "id" + anchorId;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.serializer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.DumperOptions;
|
||||
import io.jenkins.plugins.casc.snakeyaml.DumperOptions.Version;
|
||||
import io.jenkins.plugins.casc.snakeyaml.emitter.Emitable;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.AliasEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.DocumentEndEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.DocumentStartEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.ImplicitTuple;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.MappingEndEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.MappingStartEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.ScalarEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.SequenceEndEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.SequenceStartEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.StreamEndEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.events.StreamStartEvent;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.AnchorNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.CollectionNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.MappingNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Node;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.NodeId;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.NodeTuple;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.ScalarNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.SequenceNode;
|
||||
import io.jenkins.plugins.casc.snakeyaml.nodes.Tag;
|
||||
import io.jenkins.plugins.casc.snakeyaml.resolver.Resolver;
|
||||
|
||||
public final class Serializer {
|
||||
private final Emitable emitter;
|
||||
private final Resolver resolver;
|
||||
private boolean explicitStart;
|
||||
private boolean explicitEnd;
|
||||
private Version useVersion;
|
||||
private Map<String, String> useTags;
|
||||
private Set<Node> serializedNodes;
|
||||
private Map<Node, String> anchors;
|
||||
private AnchorGenerator anchorGenerator;
|
||||
private Boolean closed;
|
||||
private Tag explicitRoot;
|
||||
|
||||
public Serializer(Emitable emitter, Resolver resolver, DumperOptions opts, Tag rootTag) {
|
||||
this.emitter = emitter;
|
||||
this.resolver = resolver;
|
||||
this.explicitStart = opts.isExplicitStart();
|
||||
this.explicitEnd = opts.isExplicitEnd();
|
||||
if (opts.getVersion() != null) {
|
||||
this.useVersion = opts.getVersion();
|
||||
}
|
||||
this.useTags = opts.getTags();
|
||||
this.serializedNodes = new HashSet<Node>();
|
||||
this.anchors = new HashMap<Node, String>();
|
||||
this.anchorGenerator = opts.getAnchorGenerator();
|
||||
this.closed = null;
|
||||
this.explicitRoot = rootTag;
|
||||
}
|
||||
|
||||
public void open() throws IOException {
|
||||
if (closed == null) {
|
||||
this.emitter.emit(new StreamStartEvent(null, null));
|
||||
this.closed = Boolean.FALSE;
|
||||
} else if (Boolean.TRUE.equals(closed)) {
|
||||
throw new SerializerException("serializer is closed");
|
||||
} else {
|
||||
throw new SerializerException("serializer is already opened");
|
||||
}
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
if (closed == null) {
|
||||
throw new SerializerException("serializer is not opened");
|
||||
} else if (!Boolean.TRUE.equals(closed)) {
|
||||
this.emitter.emit(new StreamEndEvent(null, null));
|
||||
this.closed = Boolean.TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
public void serialize(Node node) throws IOException {
|
||||
if (closed == null) {
|
||||
throw new SerializerException("serializer is not opened");
|
||||
} else if (closed) {
|
||||
throw new SerializerException("serializer is closed");
|
||||
}
|
||||
this.emitter.emit(new DocumentStartEvent(null, null, this.explicitStart, this.useVersion,
|
||||
useTags));
|
||||
anchorNode(node);
|
||||
if (explicitRoot != null) {
|
||||
node.setTag(explicitRoot);
|
||||
}
|
||||
serializeNode(node, null);
|
||||
this.emitter.emit(new DocumentEndEvent(null, null, this.explicitEnd));
|
||||
this.serializedNodes.clear();
|
||||
this.anchors.clear();
|
||||
}
|
||||
|
||||
private void anchorNode(Node node) {
|
||||
if (node.getNodeId() == NodeId.anchor) {
|
||||
node = ((AnchorNode) node).getRealNode();
|
||||
}
|
||||
if (this.anchors.containsKey(node)) {
|
||||
String anchor = this.anchors.get(node);
|
||||
if (null == anchor) {
|
||||
anchor = this.anchorGenerator.nextAnchor(node);
|
||||
this.anchors.put(node, anchor);
|
||||
}
|
||||
} else {
|
||||
this.anchors.put(node, null);
|
||||
switch (node.getNodeId()) {
|
||||
case sequence:
|
||||
SequenceNode seqNode = (SequenceNode) node;
|
||||
List<Node> list = seqNode.getValue();
|
||||
for (Node item : list) {
|
||||
anchorNode(item);
|
||||
}
|
||||
break;
|
||||
case mapping:
|
||||
MappingNode mnode = (MappingNode) node;
|
||||
List<NodeTuple> map = mnode.getValue();
|
||||
for (NodeTuple object : map) {
|
||||
Node key = object.getKeyNode();
|
||||
Node value = object.getValueNode();
|
||||
anchorNode(key);
|
||||
anchorNode(value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//parent Node is not used but might be used in the future
|
||||
private void serializeNode(Node node, Node parent) throws IOException {
|
||||
if (node.getNodeId() == NodeId.anchor) {
|
||||
node = ((AnchorNode) node).getRealNode();
|
||||
}
|
||||
String tAlias = this.anchors.get(node);
|
||||
if (this.serializedNodes.contains(node)) {
|
||||
this.emitter.emit(new AliasEvent(tAlias, null, null));
|
||||
} else {
|
||||
this.serializedNodes.add(node);
|
||||
switch (node.getNodeId()) {
|
||||
case scalar:
|
||||
ScalarNode scalarNode = (ScalarNode) node;
|
||||
Tag detectedTag = this.resolver.resolve(NodeId.scalar, scalarNode.getValue(), true);
|
||||
Tag defaultTag = this.resolver.resolve(NodeId.scalar, scalarNode.getValue(), false);
|
||||
ImplicitTuple tuple = new ImplicitTuple(node.getTag().equals(detectedTag), node
|
||||
.getTag().equals(defaultTag));
|
||||
ScalarEvent event = new ScalarEvent(tAlias, node.getTag().getValue(), tuple,
|
||||
scalarNode.getValue(), null, null, scalarNode.getStyle());
|
||||
this.emitter.emit(event);
|
||||
break;
|
||||
case sequence:
|
||||
SequenceNode seqNode = (SequenceNode) node;
|
||||
boolean implicitS = node.getTag().equals(this.resolver.resolve(NodeId.sequence,
|
||||
null, true));
|
||||
this.emitter.emit(new SequenceStartEvent(tAlias, node.getTag().getValue(),
|
||||
implicitS, null, null, seqNode.getFlowStyle()));
|
||||
List<Node> list = seqNode.getValue();
|
||||
for (Node item : list) {
|
||||
serializeNode(item, node);
|
||||
}
|
||||
this.emitter.emit(new SequenceEndEvent(null, null));
|
||||
break;
|
||||
default:// instance of MappingNode
|
||||
Tag implicitTag = this.resolver.resolve(NodeId.mapping, null, true);
|
||||
boolean implicitM = node.getTag().equals(implicitTag);
|
||||
this.emitter.emit(new MappingStartEvent(tAlias, node.getTag().getValue(),
|
||||
implicitM, null, null, ((CollectionNode) node).getFlowStyle()));
|
||||
MappingNode mnode = (MappingNode) node;
|
||||
List<NodeTuple> map = mnode.getValue();
|
||||
for (NodeTuple row : map) {
|
||||
Node key = row.getKeyNode();
|
||||
Node value = row.getValueNode();
|
||||
serializeNode(key, mnode);
|
||||
serializeNode(value, mnode);
|
||||
}
|
||||
this.emitter.emit(new MappingEndEvent(null, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.serializer;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.YAMLException;
|
||||
|
||||
public class SerializerException extends YAMLException {
|
||||
private static final long serialVersionUID = 2632638197498912433L;
|
||||
|
||||
public SerializerException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.tokens;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
public final class AliasToken extends Token {
|
||||
private final String value;
|
||||
|
||||
public AliasToken(String value, Mark startMark, Mark endMark) {
|
||||
super(startMark, endMark);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Token.ID getTokenId() {
|
||||
return ID.Alias;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.tokens;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
public final class AnchorToken extends Token {
|
||||
private final String value;
|
||||
|
||||
public AnchorToken(String value, Mark startMark, Mark endMark) {
|
||||
super(startMark, endMark);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Token.ID getTokenId() {
|
||||
return ID.Anchor;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.tokens;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
public final class BlockEndToken extends Token {
|
||||
|
||||
public BlockEndToken(Mark startMark, Mark endMark) {
|
||||
super(startMark, endMark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Token.ID getTokenId() {
|
||||
return ID.BlockEnd;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.tokens;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
public final class BlockEntryToken extends Token {
|
||||
|
||||
public BlockEntryToken(Mark startMark, Mark endMark) {
|
||||
super(startMark, endMark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Token.ID getTokenId() {
|
||||
return ID.BlockEntry;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.tokens;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
public final class BlockMappingStartToken extends Token {
|
||||
|
||||
public BlockMappingStartToken(Mark startMark, Mark endMark) {
|
||||
super(startMark, endMark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Token.ID getTokenId() {
|
||||
return ID.BlockMappingStart;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.tokens;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
public final class BlockSequenceStartToken extends Token {
|
||||
|
||||
public BlockSequenceStartToken(Mark startMark, Mark endMark) {
|
||||
super(startMark, endMark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Token.ID getTokenId() {
|
||||
return ID.BlockSequenceStart;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.tokens;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
/**
|
||||
* @deprecated it will be removed because it is not used
|
||||
*/
|
||||
public class CommentToken extends Token {
|
||||
public CommentToken(Mark startMark, Mark endMark) {
|
||||
super(startMark, endMark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ID getTokenId() {
|
||||
return ID.Comment;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.tokens;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.YAMLException;
|
||||
|
||||
public final class DirectiveToken<T> extends Token {
|
||||
private final String name;
|
||||
private final List<T> value;
|
||||
|
||||
public DirectiveToken(String name, List<T> value, Mark startMark, Mark endMark) {
|
||||
super(startMark, endMark);
|
||||
this.name = name;
|
||||
if (value != null && value.size() != 2) {
|
||||
throw new YAMLException("Two strings must be provided instead of "
|
||||
+ String.valueOf(value.size()));
|
||||
}
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public List<T> getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Token.ID getTokenId() {
|
||||
return ID.Directive;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jenkins.plugins.casc.snakeyaml.tokens;
|
||||
|
||||
import io.jenkins.plugins.casc.snakeyaml.error.Mark;
|
||||
|
||||
public final class DocumentEndToken extends Token {
|
||||
|
||||
public DocumentEndToken(Mark startMark, Mark endMark) {
|
||||
super(startMark, endMark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Token.ID getTokenId() {
|
||||
return ID.DocumentEnd;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue