merge snakeyaml into source

This commit is contained in:
kimchy 2010-03-01 15:50:02 +02:00
parent 4c9cf299e6
commit 18a1a5f940
88 changed files with 8990 additions and 16 deletions

View File

@ -1,9 +0,0 @@
<component name="libraryTable">
<library name="snakeyaml">
<CLASSES>
<root url="jar://$GRADLE_REPOSITORY$/org.yaml/snakeyaml/jars/snakeyaml-1.5.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -17,7 +17,6 @@
<orderEntry type="library" exported="" name="google-collect" level="project" />
<orderEntry type="library" exported="" name="joda-time" level="project" />
<orderEntry type="library" exported="" name="jackson" level="project" />
<orderEntry type="library" exported="" name="snakeyaml" level="project" />
<orderEntry type="library" exported="" name="guice" level="project" />
<orderEntry type="library" exported="" name="jline" level="project" />
<orderEntry type="library" exported="" name="jgroups" level="project" />

View File

@ -14,3 +14,6 @@ Written by Cliff Click and released as Public Domain.
Logging abstraction provided by SLF4J (http://www.slf4j.org).
Copyright (c) 2004-2008 QOS.ch
Yaml support uses SnakeYaml Copyright of Andrey Somov under the
Apache 2 License.

View File

@ -38,7 +38,6 @@ allprojects {
repositories {
mavenCentral()
mavenRepo urls: 'http://repository.jboss.com/maven2/'
mavenRepo urls: 'http://snakeyamlrepo.appspot.com/repository' // for snakeyaml
}
}

2
gradlew vendored
View File

@ -7,7 +7,7 @@
##############################################################################
# Uncomment those lines to set JVM options. GRADLE_OPTS and JAVA_OPTS can be used together.
# GRADLE_OPTS="$GRADLE_OPTS -Xmx512"
GRADLE_OPTS="$GRADLE_OPTS -Xmx512m"
# JAVA_OPTS="$JAVA_OPTS -Xmx512"
warn ( ) {

2
gradlew.bat vendored
View File

@ -13,7 +13,7 @@
if "%OS%"=="Windows_NT" setlocal
@rem Uncomment those lines to set JVM options. GRADLE_OPTS and JAVA_OPTS can be used together.
@rem set GRADLE_OPTS=%GRADLE_OPTS% -Xmx512
set GRADLE_OPTS=%GRADLE_OPTS% -Xmx512m
@rem set JAVA_OPTS=%JAVA_OPTS% -Xmx512
set DIRNAME=%~dp0

View File

@ -36,8 +36,6 @@ dependencies {
compile 'joda-time:joda-time:1.6'
compile 'com.google.collections:google-collections:1.0'
compile 'org.yaml:snakeyaml:1.5'
compile 'org.codehaus.jackson:jackson-core-asl:1.4.2'
compile 'org.codehaus.jackson:jackson-mapper-asl:1.4.2'

View File

@ -19,7 +19,7 @@
package org.elasticsearch.util.settings.loader;
import org.yaml.snakeyaml.Yaml;
import org.elasticsearch.util.yaml.snakeyaml.Yaml;
import java.io.IOException;
import java.util.List;

View File

@ -0,0 +1,192 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml;
import org.elasticsearch.util.yaml.snakeyaml.composer.Composer;
import org.elasticsearch.util.yaml.snakeyaml.constructor.BaseConstructor;
import org.elasticsearch.util.yaml.snakeyaml.constructor.Constructor;
import org.elasticsearch.util.yaml.snakeyaml.error.YAMLException;
import org.elasticsearch.util.yaml.snakeyaml.events.Event;
import org.elasticsearch.util.yaml.snakeyaml.nodes.Node;
import org.elasticsearch.util.yaml.snakeyaml.parser.Parser;
import org.elasticsearch.util.yaml.snakeyaml.parser.ParserImpl;
import org.elasticsearch.util.yaml.snakeyaml.reader.StreamReader;
import org.elasticsearch.util.yaml.snakeyaml.resolver.Resolver;
import java.io.Reader;
import java.util.Iterator;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public class Loader {
protected final BaseConstructor constructor;
protected Resolver resolver;
private boolean attached = false;
public Loader(BaseConstructor constructor) {
super();
this.constructor = constructor;
}
public Loader() {
this(new Constructor());
}
public Object load(Reader io) {
Composer composer = new Composer(new ParserImpl(new StreamReader(io)), resolver);
constructor.setComposer(composer);
return constructor.getSingleData();
}
public Iterable<Object> loadAll(Reader yaml) {
Composer composer = new Composer(new ParserImpl(new StreamReader(yaml)), resolver);
this.constructor.setComposer(composer);
Iterator<Object> result = new Iterator<Object>() {
public boolean hasNext() {
return constructor.checkData();
}
public Object next() {
return constructor.getData();
}
public void remove() {
throw new UnsupportedOperationException();
}
};
return new YamlIterable(result);
}
/**
* Parse the first YAML document in a stream and produce the corresponding
* representation tree.
*
* @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);
this.constructor.setComposer(composer);
return composer.getSingleNode();
}
/**
* Parse all YAML documents in a stream and produce corresponding
* representation trees.
*
* @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);
this.constructor.setComposer(composer);
Iterator<Node> result = new Iterator<Node>() {
public boolean hasNext() {
return composer.checkNode();
}
public Node next() {
return composer.getNode();
}
public void remove() {
throw new UnsupportedOperationException();
}
};
return new NodeIterable(result);
}
private class NodeIterable implements Iterable<Node> {
private Iterator<Node> iterator;
public NodeIterable(Iterator<Node> iterator) {
this.iterator = iterator;
}
public Iterator<Node> iterator() {
return iterator;
}
}
private class YamlIterable implements Iterable<Object> {
private Iterator<Object> iterator;
public YamlIterable(Iterator<Object> iterator) {
this.iterator = iterator;
}
public Iterator<Object> iterator() {
return iterator;
}
}
public void setResolver(Resolver resolver) {
this.resolver = resolver;
}
/**
* Because Loader is stateful it cannot be shared
*/
void setAttached() {
if (!attached) {
attached = true;
} else {
throw new YAMLException("Loader cannot be shared.");
}
}
/**
* Parse a YAML stream and produce parsing events.
*
* @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>() {
public boolean hasNext() {
return parser.peekEvent() != null;
}
public Event next() {
return parser.getEvent();
}
public void remove() {
throw new UnsupportedOperationException();
}
};
return new EventIterable(result);
}
private class EventIterable implements Iterable<Event> {
private Iterator<Event> iterator;
public EventIterable(Iterator<Event> iterator) {
this.iterator = iterator;
}
public Iterator<Event> iterator() {
return iterator;
}
}
}

View File

@ -0,0 +1,162 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml;
import org.elasticsearch.util.yaml.snakeyaml.nodes.Tag;
import java.util.HashMap;
import java.util.Map;
/**
* Provides additional runtime information necessary to create a custom Java
* instance.
*/
public final class TypeDescription {
private final Class<? extends Object> type;
private Tag tag;
private boolean root;
private Map<String, Class<? extends Object>> listProperties;
private Map<String, Class<? extends Object>> keyProperties;
private Map<String, Class<? extends Object>> valueProperties;
public TypeDescription(Class<? extends Object> clazz, Tag tag) {
this.type = clazz;
this.tag = tag;
listProperties = new HashMap<String, Class<? extends Object>>();
keyProperties = new HashMap<String, Class<? extends Object>>();
valueProperties = new HashMap<String, Class<? extends Object>>();
}
public TypeDescription(Class<? extends Object> clazz, String tag) {
this(clazz, new Tag(tag));
}
public TypeDescription(Class<? extends Object> clazz) {
this(clazz, (Tag) null);
}
/**
* 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;
}
/**
* Defines whether this type (class) is the root of the YAML document
*
* @return true if this type shall be used as a root of object hierarchy.
*/
public boolean isRoot() {
return root;
}
/**
* Specify whether this type (class) should be serve as the root of the YAML
* document
*
* @param root true if this type shall be used as a root of object hierarchy.
*/
public void setRoot(boolean root) {
this.root = root;
}
/**
* Specify that the property is a type-safe <code>List</code>.
*
* @param property name of the JavaBean property
* @param type class of List values
*/
public void putListPropertyType(String property, Class<? extends Object> type) {
listProperties.put(property, type);
}
/**
* Get class of List values for provided JavaBean property.
*
* @param property property name
* @return class of List values
*/
public Class<? extends Object> getListPropertyType(String property) {
return listProperties.get(property);
}
/**
* 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
*/
public void putMapPropertyType(String property, Class<? extends Object> key,
Class<? extends Object> value) {
keyProperties.put(property, key);
valueProperties.put(property, value);
}
/**
* Get keys type info for this JavaBean
*
* @param property property name of this JavaBean
* @return class of keys in the Map
*/
public Class<? extends Object> getMapKeyType(String property) {
return keyProperties.get(property);
}
/**
* Get values type info for this JavaBean
*
* @param property property name of this JavaBean
* @return class of values in the Map
*/
public Class<? extends Object> getMapValueType(String property) {
return valueProperties.get(property);
}
@Override
public String toString() {
return "TypeDescription for " + getType() + " (tag='" + getTag() + "')";
}
}

View File

@ -0,0 +1,182 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml;
import org.elasticsearch.util.yaml.snakeyaml.events.Event;
import org.elasticsearch.util.yaml.snakeyaml.nodes.Node;
import org.elasticsearch.util.yaml.snakeyaml.reader.UnicodeReader;
import org.elasticsearch.util.yaml.snakeyaml.resolver.Resolver;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
/**
* Public YAML interface. Each Thread must have its own instance.
*/
public class Yaml {
private final Loader loader;
private final Resolver resolver;
private String name;
/**
* Create Yaml instance. It is safe to create a few instances and use them
* in different Threads.
*
* @param loader Loader to parse incoming documents
* @param resolver Resolver to detect implicit type
*/
public Yaml(Loader loader, Resolver resolver) {
this.loader = loader;
loader.setAttached();
this.resolver = resolver;
this.loader.setResolver(resolver);
this.name = "Yaml:" + System.identityHashCode(this);
}
public Yaml() {
this(new Loader(), new Resolver());
}
/**
* Parse the first 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)
* @return parsed object
*/
public Object load(String yaml) {
return loader.load(new StringReader(yaml));
}
/**
* Parse the first YAML document in a stream and produce the corresponding
* Java object.
*
* @param io data to load from (BOM is respected and removed)
* @return parsed object
*/
public Object load(InputStream io) {
return loader.load(new UnicodeReader(io));
}
/**
* Parse the first YAML document in a stream and produce the corresponding
* Java object.
*
* @param io data to load from (BOM must not be present)
* @return parsed object
*/
public Object load(Reader io) {
return loader.load(io);
}
/**
* Parse all YAML documents in a String and produce corresponding Java
* objects.
*
* @param yaml YAML data to load from (BOM must not be present)
* @return an iterator over the parsed Java objects in this String in proper
* sequence
*/
public Iterable<Object> loadAll(Reader yaml) {
return loader.loadAll(yaml);
}
/**
* Parse all YAML documents in a String and produce corresponding Java
* objects. (Because the encoding in known BOM is not respected.)
*
* @param yaml YAML data to load from (BOM must not be present)
* @return an iterator 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.
*
* @param yaml YAML data to load from (BOM is respected and ignored)
* @return an iterator 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.
*
* @param io stream of a YAML document
* @return parsed root Node for the specified YAML document
*/
public Node compose(Reader io) {
return loader.compose(io);
}
/**
* Parse all YAML documents in a stream and produce corresponding
* representation trees.
*
* @param io stream of YAML documents
* @return parsed root Nodes for all the specified YAML documents
*/
public Iterable<Node> composeAll(Reader io) {
return loader.composeAll(io);
}
@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.
*
* @param yaml YAML document(s)
* @return parsed events
*/
public Iterable<Event> parse(Reader yaml) {
return loader.parse(yaml);
}
}

View File

@ -0,0 +1,224 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.composer;
import org.elasticsearch.util.yaml.snakeyaml.events.*;
import org.elasticsearch.util.yaml.snakeyaml.nodes.*;
import org.elasticsearch.util.yaml.snakeyaml.parser.Parser;
import org.elasticsearch.util.yaml.snakeyaml.resolver.Resolver;
import java.util.*;
/**
* 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 {
private 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() {
// Get the root node of the next document.
if (!parser.checkEvent(Event.ID.StreamEnd)) {
return composeDocument();
} else {
return (Node) null;
}
}
/**
* 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 = composeDocument();
}
// 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 composeDocument() {
// Drop the DOCUMENT-START event.
parser.getEvent();
// Compose the root node.
Node node = composeNode(null, null);
// Drop the DOCUMENT-END event.
parser.getEvent();
this.anchors.clear();
recursiveNodes.clear();
return node;
}
private Node composeNode(Node parent, Object index) {
recursiveNodes.add(parent);
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 result = (Node) anchors.get(anchor);
if (recursiveNodes.remove(result)) {
result.setTwoStepsConstruction(true);
}
return result;
}
NodeEvent event = (NodeEvent) parser.peekEvent();
String anchor = null;
anchor = event.getAnchor();
if (anchor != null && anchors.containsKey(anchor)) {
throw new ComposerException("found duplicate anchor " + anchor + "; first occurence",
this.anchors.get(anchor).getStartMark(), "second occurence", event
.getStartMark());
}
// resolver.descendResolver(parent, index);
Node node = null;
if (parser.checkEvent(Event.ID.Scalar)) {
node = composeScalarNode(anchor);
} else if (parser.checkEvent(Event.ID.SequenceStart)) {
node = composeSequenceNode(anchor);
} else {
node = composeMappingNode(anchor);
}
// resolver.ascendResolver();
recursiveNodes.remove(parent);
return node;
}
private 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().isFirst());
resolved = true;
} else {
nodeTag = new Tag(tag);
}
Node node = new ScalarNode(nodeTag, resolved, ev.getValue(), ev.getStartMark(), ev
.getEndMark(), ev.getStyle());
if (anchor != null) {
anchors.put(anchor, node);
}
return node;
}
private 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);
}
SequenceNode node = new SequenceNode(nodeTag, resolved, new ArrayList<Node>(), startEvent
.getStartMark(), null, startEvent.getFlowStyle());
if (anchor != null) {
anchors.put(anchor, node);
}
int index = 0;
while (!parser.checkEvent(Event.ID.SequenceEnd)) {
(node.getValue()).add(composeNode(node, index));
index++;
}
Event endEvent = parser.getEvent();
node.setEndMark(endEvent.getEndMark());
return node;
}
private 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);
}
MappingNode node = new MappingNode(nodeTag, resolved, new ArrayList<NodeTuple>(),
startEvent.getStartMark(), null, startEvent.getFlowStyle());
if (anchor != null) {
anchors.put(anchor, node);
}
while (!parser.checkEvent(Event.ID.MappingEnd)) {
Node itemKey = composeNode(node, null);
Node itemValue = composeNode(node, itemKey);
node.getValue().add(new NodeTuple(itemKey, itemValue));
}
Event endEvent = parser.getEvent();
node.setEndMark(endEvent.getEndMark());
return node;
}
}

View File

@ -0,0 +1,33 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.composer;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
import org.elasticsearch.util.yaml.snakeyaml.error.MarkedYAMLException;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
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);
}
}

View File

@ -0,0 +1,44 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.constructor;
import org.elasticsearch.util.yaml.snakeyaml.error.YAMLException;
import org.elasticsearch.util.yaml.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 org.elasticsearch.util.yaml.snakeyaml.constructor.Construct#construct2ndStep(org.elasticsearch.util.yaml.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);
}
}
}

View File

@ -0,0 +1,338 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.constructor;
import org.elasticsearch.util.yaml.snakeyaml.composer.Composer;
import org.elasticsearch.util.yaml.snakeyaml.composer.ComposerException;
import org.elasticsearch.util.yaml.snakeyaml.error.YAMLException;
import org.elasticsearch.util.yaml.snakeyaml.nodes.*;
import java.util.*;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
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: <br/>
* 1) explicit tag - if present. <br/>
* 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>();
private Composer composer;
private 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;
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>>();
rootTag = null;
}
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
*
* @return constructed instance
* @throws ComposerException in case there are more documents in the stream
*/
public Object getSingleData() {
// Ensure that the stream contains a single document and construct it
Node node = composer.getSingleNode();
if (node != null) {
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
*/
private 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);
}
if (recursiveObjects.contains(node)) {
throw new ConstructorException(null, null, "found unconstructable recursive node", node
.getStartMark());
}
recursiveObjects.add(node);
Construct constructor = getConstructor(node);
Object data = constructor.construct(node);
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 Node to be constructed
* @return 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 Object constructScalar(ScalarNode node) {
return node.getValue();
}
protected List<Object> createDefaultList(int initSize) {
return new ArrayList<Object>(initSize);
}
@SuppressWarnings("unchecked")
protected List<? extends Object> constructSequence(SequenceNode node) {
List<Object> result;
if (List.class.isAssignableFrom(node.getType()) && !node.getType().isInterface()) {
// the root class may be defined (Vector for instance)
try {
result = (List<Object>) node.getType().newInstance();
} catch (Exception e) {
throw new YAMLException(e);
}
} else {
result = createDefaultList(node.getValue().size());
}
constructSequenceStep2(node, result);
return result;
}
protected void constructSequenceStep2(SequenceNode node, List<Object> list) {
for (Node child : node.getValue()) {
list.add(constructObject(child));
}
}
protected Map<Object, Object> createDefaultMap() {
// respect order from YAML document
return new LinkedHashMap<Object, Object>();
}
protected Set<Object> createDefaultSet() {
// respect order from YAML document
return new LinkedHashSet<Object>();
}
protected Set<Object> constructSet(MappingNode node) {
Set<Object> set = createDefaultSet();
constructSet2ndStep(node, set);
return set;
}
protected Map<Object, Object> constructMapping(MappingNode node) {
Map<Object, Object> mapping = createDefaultMap();
constructMapping2ndStep(node, mapping);
return mapping;
}
protected void constructMapping2ndStep(MappingNode node, Map<Object, Object> mapping) {
List<NodeTuple> nodeValue = (List<NodeTuple>) 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 = (List<NodeTuple>) 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);
}
}
}
// 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;
// }
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;
}
}
}

View File

@ -0,0 +1,49 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.constructor;
import org.elasticsearch.util.yaml.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 http://yaml.org/spec/1.1/#id859109
*/
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
*/
public 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
*/
public void construct2ndStep(Node node, Object object);
}

View File

@ -0,0 +1,608 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.constructor;
import org.elasticsearch.util.yaml.snakeyaml.TypeDescription;
import org.elasticsearch.util.yaml.snakeyaml.error.YAMLException;
import org.elasticsearch.util.yaml.snakeyaml.introspector.FieldProperty;
import org.elasticsearch.util.yaml.snakeyaml.introspector.MethodProperty;
import org.elasticsearch.util.yaml.snakeyaml.introspector.Property;
import org.elasticsearch.util.yaml.snakeyaml.nodes.*;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
/**
* Construct a custom Java instance.
*/
public class Constructor extends SafeConstructor {
private final Map<Tag, Class<? extends Object>> typeTags;
private final Map<Class<? extends Object>, TypeDescription> typeDefinitions;
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) {
if (theRoot == null) {
throw new NullPointerException("Root type must be provided.");
}
this.yamlConstructors.put(null, new ConstructYamlObject());
if (!Object.class.equals(theRoot)) {
rootTag = new Tag(theRoot);
}
typeTags = new HashMap<Tag, Class<? extends Object>>();
typeDefinitions = new HashMap<Class<? extends Object>, TypeDescription>();
yamlClassConstructors.put(NodeId.scalar, new ConstructScalar());
yamlClassConstructors.put(NodeId.mapping, new ConstructMapping());
yamlClassConstructors.put(NodeId.sequence, new ConstructSequence());
}
/**
* 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
*/
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;
}
/**
* 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.");
}
if (rootTag == null && definition.isRoot()) {
rootTag = new Tag(definition.getType());
}
Tag tag = definition.getTag();
typeTags.put(tag, definition.getType());
return typeDefinitions.put(definition.getType(), definition);
}
/**
* Construct mapping instance (Map, JavaBean) when the runtime class is
* known.
*/
private class ConstructMapping implements Construct {
private final Map<Class<? extends Object>, Map<String, Property>> propertiesCache = new HashMap<Class<? extends Object>, Map<String, Property>>();
/**
* 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 (Properties.class.isAssignableFrom(node.getType())) {
Properties properties = new Properties();
if (!node.isTwoStepsConstruction()) {
constructMapping2ndStep(mnode, (Map<Object, Object>) properties);
} else {
throw new YAMLException("Properties must not be recursive.");
}
return properties;
} else if (SortedMap.class.isAssignableFrom(node.getType())) {
SortedMap<Object, Object> map = new TreeMap<Object, Object>();
if (!node.isTwoStepsConstruction()) {
constructMapping2ndStep(mnode, map);
}
return map;
} else if (Map.class.isAssignableFrom(node.getType())) {
if (node.isTwoStepsConstruction()) {
return createDefaultMap();
} else {
return constructMapping(mnode);
}
} else if (SortedSet.class.isAssignableFrom(node.getType())) {
SortedSet<Object> set = new TreeSet<Object>();
if (!node.isTwoStepsConstruction()) {
constructSet2ndStep(mnode, set);
}
return set;
} else if (Set.class.isAssignableFrom(node.getType())) {
if (node.isTwoStepsConstruction()) {
return createDefaultSet();
} else {
return constructSet(mnode);
}
} else {
if (node.isTwoStepsConstruction()) {
return createEmptyJavaBean(mnode);
} else {
return constructJavaBean2ndStep(mnode, createEmptyJavaBean(mnode));
}
}
}
@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);
}
}
private Object createEmptyJavaBean(MappingNode node) {
try {
Class<? extends Object> type = node.getType();
if (Modifier.isAbstract(type.getModifiers())) {
node.setType(getClassForNode(node));
}
/**
* 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.
*/
return node.getType().newInstance();
} catch (InstantiationException e) {
throw new YAMLException(e);
} catch (IllegalAccessException e) {
throw new YAMLException(e);
}
}
@SuppressWarnings("unchecked")
private Object constructJavaBean2ndStep(MappingNode node, Object object) {
Class<? extends Object> beanType = node.getType();
List<NodeTuple> nodeValue = (List<NodeTuple>) 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);
boolean isArray = false;
try {
Property property = getProperty(beanType, key);
valueNode.setType(property.getType());
if (property.getType().isArray()) {
isArray = true;
}
TypeDescription memberDescription = typeDefinitions.get(beanType);
boolean typeDetected = false;
if (memberDescription != null) {
switch (valueNode.getNodeId()) {
case sequence:
SequenceNode snode = (SequenceNode) valueNode;
Class<? extends Object> memberType = memberDescription
.getListPropertyType(key);
if (memberType != null) {
snode.setListType(memberType);
typeDetected = true;
} else if (property.getType().isArray()) {
isArray = true;
snode.setListType(property.getType().getComponentType());
typeDetected = true;
}
break;
case mapping:
MappingNode mnode = (MappingNode) valueNode;
Class<? extends Object> keyType = memberDescription.getMapKeyType(key);
if (keyType != null) {
mnode.setKeyType(keyType);
mnode.setValueType(memberDescription.getMapValueType(key));
typeDetected = true;
}
break;
}
}
if (!typeDetected && valueNode.getNodeId() != NodeId.scalar) {
// only if there is no explicit TypeDescription
Type[] arguments = property.getActualTypeArguments();
if (arguments != null) {
// type safe (generic) collection may contain the
// proper class
if (valueNode.getNodeId() == NodeId.sequence) {
Class t = (Class) arguments[0];
SequenceNode snode = (SequenceNode) valueNode;
snode.setListType(t);
} else if (valueNode.getTag().equals(Tag.SET)) {
Class t = (Class) arguments[0];
MappingNode mnode = (MappingNode) valueNode;
mnode.setKeyType(t);
mnode.setUseClassConstructor(true);
} else if (valueNode.getNodeId() == NodeId.mapping) {
Class ketType = (Class) arguments[0];
Class valueType = (Class) arguments[1];
MappingNode mnode = (MappingNode) valueNode;
mnode.setKeyType(ketType);
mnode.setValueType(valueType);
mnode.setUseClassConstructor(true);
}
}
}
Object value = constructObject(valueNode);
if (isArray && value instanceof List) {
List<Object> list = (List<Object>) value;
value = list.toArray(createArray(property.getType()));
}
property.set(object, value);
} catch (Exception e) {
throw new YAMLException("Cannot create property=" + key + " for JavaBean="
+ object + "; " + e.getMessage(), e);
}
}
return object;
}
@SuppressWarnings("unchecked")
private <T> T[] createArray(Class<T> type) {
return (T[]) Array.newInstance(type.getComponentType(), 0);
}
private Property getProperty(Class<? extends Object> type, String name)
throws IntrospectionException {
// check cache
Map<String, Property> properties = propertiesCache.get(type);
if (properties == null) {
properties = new HashMap<String, Property>();
propertiesCache.put(type, properties);
for (PropertyDescriptor property : Introspector.getBeanInfo(type)
.getPropertyDescriptors()) {
String methodName = property.getName();
if (property.getWriteMethod() != null) {
properties.put(methodName, new MethodProperty(property));
}
}
for (Field field : type.getFields()) {
int modifiers = field.getModifiers();
if (Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers)) {
continue;
}
properties.put(field.getName(), new FieldProperty(field));
}
}
// take from cache
Property property = properties.get(name);
if (property == null) {
throw new YAMLException("Unable to find property '" + name + "' on class: "
+ type.getName());
} else {
return property;
}
}
}
/**
* 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)
*/
private class ConstructYamlObject implements Construct {
@SuppressWarnings("unchecked")
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) {
Object result = null;
try {
result = getConstructor(node).construct(node);
} catch (Exception e) {
throw new ConstructorException(null, null, "Can't construct a java object for "
+ node.getTag() + "; exception=" + e.getMessage(), node.getStartMark(), e);
}
return result;
}
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 {
@SuppressWarnings("unchecked")
public Object construct(Node nnode) {
ScalarNode node = (ScalarNode) nnode;
Class type = node.getType();
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)) {
// standard classes created directly
result = constructStandardJavaInstance(type, node);
} else {
// there must be only 1 constructor with 1 argument
java.lang.reflect.Constructor[] javaConstructors = type.getConstructors();
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) {
throw new YAMLException("No single argument constructor found for " + type);
} 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.getConstructor(String.class);
} catch (Exception e) {
throw new ConstructorException(null, null,
"Can't construct a java object for scalar " + node.getTag()
+ "; No String constructor found. Exception="
+ e.getMessage(), node.getStartMark(), e);
}
}
try {
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(Class type, ScalarNode node) {
Object result;
if (type == String.class) {
Construct stringConstructor = yamlConstructors.get(Tag.STR);
result = stringConstructor.construct((ScalarNode) node);
} else if (type == Boolean.class || type == Boolean.TYPE) {
Construct boolConstructor = yamlConstructors.get(Tag.BOOL);
result = boolConstructor.construct((ScalarNode) node);
} else if (type == Character.class || type == Character.TYPE) {
Construct charConstructor = yamlConstructors.get(Tag.STR);
String ch = (String) charConstructor.construct((ScalarNode) node);
if (ch.length() == 0) {
result = null;
} else if (ch.length() != 1) {
throw new YAMLException("Invalid node Character: '" + ch + "'; length: "
+ ch.length());
} else {
result = new Character(ch.charAt(0));
}
} else if (Date.class.isAssignableFrom(type)) {
Construct dateConstructor = yamlConstructors.get(Tag.TIMESTAMP);
Date date = (Date) dateConstructor.construct((ScalarNode) node);
if (type == Date.class) {
result = date;
} else {
try {
java.lang.reflect.Constructor<?> constr = type.getConstructor(long.class);
result = constr.newInstance(date.getTime());
} 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 = new Float((Double) result);
}
}
} 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 = new Byte(result.toString());
} else if (type == Short.class || type == Short.TYPE) {
result = new Short(result.toString());
} else if (type == Integer.class || type == Integer.TYPE) {
result = new Integer(result.toString());
} else if (type == Long.class || type == Long.TYPE) {
result = new Long(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 {
throw new YAMLException("Unsupported class: " + type);
}
return result;
}
}
/**
* Construct sequence (List, Array, or immutable object) when the runtime
* class is known.
*/
private class ConstructSequence implements Construct {
@SuppressWarnings("unchecked")
public Object construct(Node node) {
SequenceNode snode = (SequenceNode) node;
if (List.class.isAssignableFrom(node.getType()) || node.getType().isArray()) {
if (node.isTwoStepsConstruction()) {
return createDefaultList(snode.getValue().size());
} else {
return constructSequence(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().getConstructors()) {
if (snode.getValue().size() == constructor.getParameterTypes().length) {
possibleConstructors.add(constructor);
}
}
if (possibleConstructors.isEmpty()) {
throw new YAMLException("No constructors with "
+ String.valueOf(snode.getValue().size()) + " arguments found for "
+ node.getType());
}
List<Object> argumentList;
if (possibleConstructors.size() == 1) {
argumentList = new ArrayList<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);
Object argumentValue = constructObject(argumentNode);
argumentList.add(argumentValue);
index++;
}
} else {
// use BaseConstructor
argumentList = (List<Object>) constructSequence(snode);
}
Class[] parameterTypes = new Class[argumentList.size()];
int index = 0;
for (Object parameter : argumentList) {
parameterTypes[index] = parameter.getClass();
index++;
}
java.lang.reflect.Constructor javaConstructor;
try {
Class cl = node.getType();
javaConstructor = cl.getConstructor(parameterTypes);
Object[] initargs = argumentList.toArray();
return javaConstructor.newInstance(initargs);
} catch (Exception e) {
throw new YAMLException(e);
}
}
}
@SuppressWarnings("unchecked")
public void construct2ndStep(Node node, Object object) {
SequenceNode snode = (SequenceNode) node;
List<Object> list = (List<Object>) object;
if (List.class.isAssignableFrom(node.getType())) {
constructSequenceStep2(snode, list);
} 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 {
return Class.forName(name);
}
}

View File

@ -0,0 +1,39 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.constructor;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
import org.elasticsearch.util.yaml.snakeyaml.error.MarkedYAMLException;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
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);
}
}

View File

@ -0,0 +1,43 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.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);
}
}

View File

@ -0,0 +1,454 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.constructor;
import org.elasticsearch.util.yaml.snakeyaml.error.YAMLException;
import org.elasticsearch.util.yaml.snakeyaml.nodes.*;
import org.elasticsearch.util.yaml.snakeyaml.util.Base64Coder;
import java.math.BigInteger;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Construct standard Java classes
*
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public class SafeConstructor extends BaseConstructor {
public static 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);
}
private void flattenMapping(MappingNode node) {
List<NodeTuple> merge = new ArrayList<NodeTuple>();
int index = 0;
List<NodeTuple> nodeValue = (List<NodeTuple>) node.getValue();
while (index < nodeValue.size()) {
Node keyNode = nodeValue.get(index).getKeyNode();
Node valueNode = nodeValue.get(index).getValueNode();
if (keyNode.getTag().equals(Tag.MERGE)) {
nodeValue.remove(index);
switch (valueNode.getNodeId()) {
case mapping:
MappingNode mn = (MappingNode) valueNode;
flattenMapping(mn);
merge.addAll(mn.getValue());
break;
case sequence:
List<List<NodeTuple>> submerge = new ArrayList<List<NodeTuple>>();
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;
flattenMapping(mnode);
submerge.add(mnode.getValue());
}
Collections.reverse(submerge);
for (List<NodeTuple> value : submerge) {
merge.addAll(value);
}
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 if (keyNode.getTag().equals(Tag.VALUE)) {
keyNode.setTag(Tag.STR);
index++;
} else {
index++;
}
}
if (!merge.isEmpty()) {
merge.addAll(nodeValue);
((MappingNode) node).setValue(merge);
}
}
protected void constructMapping2ndStep(MappingNode node, Map<Object, Object> mapping) {
flattenMapping(node);
super.constructMapping2ndStep(node, mapping);
}
@Override
protected void constructSet2ndStep(MappingNode node, java.util.Set<Object> set) {
flattenMapping(node);
super.constructSet2ndStep(node, set);
}
private class ConstructYamlNull extends AbstractConstruct {
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);
}
private class ConstructYamlBool extends AbstractConstruct {
public Object construct(Node node) {
String val = (String) constructScalar((ScalarNode) node);
return BOOL_VALUES.get(val.toLowerCase());
}
}
private class ConstructYamlInt extends AbstractConstruct {
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 new Integer(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;
}
private class ConstructYamlFloat extends AbstractConstruct {
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 new Double(sign == -1 ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY);
} else if (".nan".equals(valLower)) {
return new Double(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 new Double(sign * val);
} else {
Double d = Double.valueOf(value);
return new Double(d.doubleValue() * sign);
}
}
}
private class ConstructYamlBinary extends AbstractConstruct {
public Object construct(Node node) {
byte[] decoded = Base64Coder.decode(constructScalar((ScalarNode) node).toString()
.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]?)$");
protected class ConstructYamlTimestamp extends AbstractConstruct {
private Calendar calendar;
public Calendar getCalendar() {
return calendar;
}
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);
String sec_s = match.group(6);
String fract_s = match.group(7);
String timezoneh_s = match.group(8);
String timezonem_s = match.group(9);
int usec = 0;
if (fract_s != null) {
usec = Integer.parseInt(fract_s);
if (usec != 0) {
while (10 * usec < 1000) {
usec *= 10;
}
}
}
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, Integer.parseInt(sec_s));
calendar.set(Calendar.MILLISECOND, usec);
return calendar.getTime();
}
}
}
private class ConstructYamlOmap extends AbstractConstruct {
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;
}
}
// Note: the same code as `construct_yaml_omap`.
private class ConstructYamlPairs extends AbstractConstruct {
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;
}
}
private class ConstructYamlSet implements Construct {
public Object construct(Node node) {
if (node.isTwoStepsConstruction()) {
return createDefaultSet();
} else {
return constructSet((MappingNode) node);
}
}
@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);
}
}
}
private class ConstructYamlStr extends AbstractConstruct {
public Object construct(Node node) {
return (String) constructScalar((ScalarNode) node);
}
}
private class ConstructYamlSeq implements Construct {
public Object construct(Node node) {
SequenceNode seqNode = (SequenceNode) node;
if (node.isTwoStepsConstruction()) {
return createDefaultList((seqNode.getValue()).size());
} else {
return constructSequence(seqNode);
}
}
@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);
}
}
}
private class ConstructYamlMap implements Construct {
public Object construct(Node node) {
if (node.isTwoStepsConstruction()) {
return createDefaultMap();
} else {
return constructMapping((MappingNode) node);
}
}
@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);
}
}
}
private static final class ConstructUndefined extends AbstractConstruct {
public Object construct(Node node) {
throw new ConstructorException(null, null,
"could not determine a constructor for the tag " + node.getTag(), node
.getStartMark());
}
}
}

View File

@ -0,0 +1,128 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.error;
import org.elasticsearch.util.yaml.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.
*
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public final class Mark {
private String name;
private int line;
private int column;
private String buffer;
private int pointer;
public Mark(String name, int index, int line, int column, String buffer, int pointer) {
super();
this.name = name;
this.line = line;
this.column = column;
this.buffer = buffer;
this.pointer = pointer;
}
private boolean isLineBreak(char ch) {
return Constant.NULL_OR_LINEBR.has(ch);
}
public String get_snippet(int indent, int max_length) {
if (buffer == null) {
return null;
}
float half = max_length / 2 - 1;
int start = pointer;
String head = "";
while ((start > 0) && (!isLineBreak(buffer.charAt(start - 1)))) {
start -= 1;
if (pointer - start > half) {
head = " ... ";
start += 5;
break;
}
}
String tail = "";
int end = pointer;
while ((end < buffer.length()) && (!isLineBreak(buffer.charAt(end)))) {
end += 1;
if (end - pointer > half) {
tail = " ... ";
end -= 5;
break;
}
}
String snippet = buffer.substring(start, end);
StringBuilder result = new StringBuilder();
for (int i = 0; i < indent; i++) {
result.append(" ");
}
result.append(head);
result.append(snippet);
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 where = new StringBuilder(" in \"");
where.append(name);
where.append("\", line ");
where.append(line + 1);
where.append(", column ");
where.append(column + 1);
if (snippet != null) {
where.append(":\n");
where.append(snippet);
}
return where.toString();
}
public String getName() {
return name;
}
/**
* starts with 0
*/
public int getLine() {
return line;
}
/**
* starts with 0
*/
public int getColumn() {
return column;
}
}

View File

@ -0,0 +1,102 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.error;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
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, 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 toString() {
StringBuilder lines = new StringBuilder();
if (context != null) {
lines.append(context);
lines.append("\n");
}
if (contextMark != null
&& (problem == null || problemMark == null
|| (contextMark.getName() != 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;
}
}

View File

@ -0,0 +1,38 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.error;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
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);
}
}

View File

@ -0,0 +1,35 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.events;
import org.elasticsearch.util.yaml.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);
}
@Override
public boolean is(ID id) {
return ID.Alias == id;
}
}

View File

@ -0,0 +1,31 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.events;
import org.elasticsearch.util.yaml.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);
}
}

View File

@ -0,0 +1,76 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.events;
import org.elasticsearch.util.yaml.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 Boolean flowStyle;
public CollectionStartEvent(String anchor, String tag, boolean implicit, Mark startMark,
Mark endMark, Boolean flowStyle) {
super(anchor, startMark, endMark);
this.tag = tag;
this.implicit = implicit;
this.flowStyle = 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 Boolean getFlowStyle() {
return this.flowStyle;
}
@Override
protected String getArguments() {
return super.getArguments() + ", tag=" + tag + ", implicit=" + implicit;
}
}

View File

@ -0,0 +1,45 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.events;
import org.elasticsearch.util.yaml.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(ID id) {
return ID.DocumentEnd == id;
}
}

View File

@ -0,0 +1,74 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.events;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
import java.util.Map;
/**
* 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 Integer[] version;
private final Map<String, String> tags;
public DocumentStartEvent(Mark startMark, Mark endMark, boolean explicit, Integer[] 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 Integer[] 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(ID id) {
return ID.DocumentStart == id;
}
}

View File

@ -0,0 +1,74 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.events;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* Basic unit of output from a {@link org.elasticsearch.util.yaml.snakeyaml.parser.Parser} or input
* of a {@link org.elasticsearch.util.yaml.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;
}
/**
* @see __repr__ for Event in PyYAML
*/
protected String getArguments() {
return "";
}
public abstract boolean is(ID id);
/*
* for tests only
*/
@Override
public boolean equals(Object obj) {
if (obj instanceof Event) {
return toString().equals(obj.toString());
} else {
return false;
}
}
}

View File

@ -0,0 +1,62 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.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 http://pyyaml.org/wiki/PyYAMLDocumentation#Events
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
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 isFirst() {
return plain;
}
/**
* @return true when tag may be omitted when the scalar is emitted in a
* non-plain style.
*/
public boolean isSecond() {
return nonPlain;
}
public boolean bothFalse() {
return !plain && !nonPlain;
}
@Override
public String toString() {
return "implicit=[" + plain + ", " + nonPlain + "]";
}
}

View File

@ -0,0 +1,38 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.events;
import org.elasticsearch.util.yaml.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(ID id) {
return ID.MappingEnd == id;
}
}

View File

@ -0,0 +1,47 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.events;
import org.elasticsearch.util.yaml.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, Boolean flowStyle) {
super(anchor, tag, implicit, startMark, endMark, flowStyle);
}
@Override
public boolean is(ID id) {
return ID.MappingStart == id;
}
}

View File

@ -0,0 +1,52 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.events;
import org.elasticsearch.util.yaml.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;
}
}

View File

@ -0,0 +1,103 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.events;
import org.elasticsearch.util.yaml.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 Character 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, Character style) {
super(anchor, startMark, endMark);
this.tag = tag;
this.implicit = implicit;
this.value = value;
this.style = 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>''</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>
*
* @return Style of the scalar.
* @see http://yaml.org/spec/1.1/#id864487
*/
public Character getStyle() {
return this.style;
}
/**
* 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(ID id) {
return ID.Scalar == id;
}
}

View File

@ -0,0 +1,38 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.events;
import org.elasticsearch.util.yaml.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(ID id) {
return ID.SequenceEnd == id;
}
}

View File

@ -0,0 +1,42 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.events;
import org.elasticsearch.util.yaml.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, Boolean flowStyle) {
super(anchor, tag, implicit, startMark, endMark, flowStyle);
}
@Override
public boolean is(ID id) {
return ID.SequenceStart == id;
}
}

View File

@ -0,0 +1,43 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.events;
import org.elasticsearch.util.yaml.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(ID id) {
return ID.StreamEnd == id;
}
}

View File

@ -0,0 +1,44 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.events;
import org.elasticsearch.util.yaml.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(ID id) {
return ID.StreamStart == id;
}
}

View File

@ -0,0 +1,59 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.introspector;
import org.elasticsearch.util.yaml.snakeyaml.error.YAMLException;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class FieldProperty extends Property {
private final Field field;
public FieldProperty(Field field) {
super(field.getName(), field.getType());
this.field = field;
}
@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 Type[] getActualTypeArguments() {
if (field.getGenericType() instanceof ParameterizedType) {
ParameterizedType t = (ParameterizedType) field.getGenericType();
return t.getActualTypeArguments();
} else {
return null;
}
}
}

View File

@ -0,0 +1,69 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.introspector;
import org.elasticsearch.util.yaml.snakeyaml.error.YAMLException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class MethodProperty extends Property {
private final PropertyDescriptor property;
public MethodProperty(PropertyDescriptor property) {
super(property.getName(), property.getPropertyType());
this.property = property;
}
@Override
public void set(Object object, Object value) throws Exception {
property.getWriteMethod().invoke(object, value);
}
@Override
public Type[] getActualTypeArguments() {
if (List.class.isAssignableFrom(property.getPropertyType())
|| Set.class.isAssignableFrom(property.getPropertyType())
|| Map.class.isAssignableFrom(property.getPropertyType())) {
if (property.getReadMethod().getGenericReturnType() instanceof ParameterizedType) {
ParameterizedType grt = (ParameterizedType) property.getReadMethod()
.getGenericReturnType();
return grt.getActualTypeArguments();
} else {
return null;
}
} else {
return null;
}
}
@Override
public Object get(Object object) {
try {
return property.getReadMethod().invoke(object);
} catch (Exception e) {
throw new YAMLException("Unable to find getter for property '" + property.getName()
+ "' on object " + object + ":" + e);
}
}
}

View File

@ -0,0 +1,54 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.introspector;
import java.lang.reflect.Type;
public abstract class Property implements Comparable<Property> {
private final String name;
private final Class<? extends Object> type;
public Property(String name, Class<? extends Object> type) {
this.name = name;
this.type = type;
}
public Class<? extends Object> getType() {
return type;
}
public abstract Type[] getActualTypeArguments();
public String getName() {
return name;
}
@Override
public String toString() {
return getName() + " of " + getType();
}
public int compareTo(Property o) {
return name.compareTo(o.name);
}
abstract public void set(Object object, Object value) throws Exception;
abstract public Object get(Object object);
}

View File

@ -0,0 +1,52 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.nodes;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* Base class for the two collection types {@link MappingNode mapping} and
* {@link SequenceNode collection}.
*/
public abstract class CollectionNode extends Node {
private Boolean flowStyle;
public CollectionNode(Tag tag, Mark startMark, Mark endMark, Boolean flowStyle) {
super(tag, startMark, endMark);
this.flowStyle = flowStyle;
}
/**
* Serialization style of this collection.
*
* @return <code>true</code> for flow style, <code>false</code> for block
* style.
*/
public Boolean getFlowStyle() {
return flowStyle;
}
public void setFlowStyle(Boolean flowStyle) {
this.flowStyle = flowStyle;
}
public void setEndMark(Mark endMark) {
this.endMark = endMark;
}
}

View File

@ -0,0 +1,97 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.nodes;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
import java.util.List;
/**
* Represents a map.
* <p>
* A map is a collection of unsorted key-value pairs.
* </p>
*/
public class MappingNode extends CollectionNode {
private Class<? extends Object> keyType;
private Class<? extends Object> valueType;
private List<NodeTuple> value;
public MappingNode(Tag tag, boolean resolved, List<NodeTuple> value, Mark startMark,
Mark endMark, Boolean flowStyle) {
super(tag, startMark, endMark, flowStyle);
if (value == null) {
throw new NullPointerException("value in a Node is required.");
}
this.value = value;
keyType = Object.class;
valueType = Object.class;
this.resolved = resolved;
}
public MappingNode(Tag tag, List<NodeTuple> value, Boolean flowStyle) {
this(tag, true, value, null, null, flowStyle);
}
@Override
public NodeId getNodeId() {
return NodeId.mapping;
}
/**
* Returns the entries of this map.
*
* @return List of entries.
*/
public List<NodeTuple> getValue() {
for (NodeTuple nodes : value) {
nodes.getKeyNode().setType(keyType);
nodes.getValueNode().setType(valueType);
}
return value;
}
public void setValue(List<NodeTuple> merge) {
value = merge;
}
public void setKeyType(Class<? extends Object> keyType) {
this.keyType = keyType;
}
public void setValueType(Class<? extends Object> valueType) {
this.valueType = valueType;
}
@Override
public String toString() {
String values;
StringBuilder buf = new StringBuilder();
for (NodeTuple node : getValue()) {
buf.append("{ key=");
buf.append(node.getKeyNode());
buf.append("; value=Node<");
// to avoid overflow in case of recursive structures
buf.append(System.identityHashCode(node.getValueNode()));
buf.append("> }");
}
values = buf.toString();
return "<" + this.getClass().getName() + " (tag=" + getTag() + ", values=" + values + ")>";
}
}

View File

@ -0,0 +1,167 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.nodes;
import org.elasticsearch.util.yaml.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 org.elasticsearch.util.yaml.snakeyaml.composer.Composer}, and later transformed into
* application specific Java classes by the classes from the
* {@link org.elasticsearch.util.yaml.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;
}
/**
* For error reporting.
*
* @return scalar, sequence, mapping
* @see class variable 'id' in PyYAML
*/
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;
}
/*
* It is not allowed to overwrite this method. Two Nodes are never equal.
*/
@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) {
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 org.elasticsearch.util.yaml.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 (isResolved() && !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 org.elasticsearch.util.yaml.snakeyaml.resolver.Resolver}.
*
* @return <code>true</code> if the tag of this node was resolved</code>
*/
public boolean isResolved() {
return resolved;
}
}

View File

@ -0,0 +1,26 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.nodes;
/**
* Enum for the three basic YAML types: scalar, sequence and mapping.
*/
public enum NodeId {
scalar, sequence, mapping;
}

View File

@ -0,0 +1,58 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.nodes;
/**
* Stores one key value pair used in a map.
*/
public class NodeTuple {
private final Node keyNode;
private final 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.
*/
public Node getKeyNode() {
return keyNode;
}
/**
* Value node.
*
* @return value
*/
public Node getValueNode() {
return valueNode;
}
@Override
public String toString() {
return "<NodeTuple keyNode=" + keyNode.toString() + "; valueNode=" + valueNode.toString()
+ ">";
}
}

View File

@ -0,0 +1,77 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.nodes;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* Represents a scalar node.
* <p>
* Scalar nodes form the leaves in the node graph.
* </p>
*/
public class ScalarNode extends Node {
private Character style;
private String value;
public ScalarNode(Tag tag, String value, Mark startMark, Mark endMark, Character style) {
this(tag, true, value, startMark, endMark, style);
}
public ScalarNode(Tag tag, boolean resolved, String value, Mark startMark, Mark endMark,
Character style) {
super(tag, startMark, endMark);
if (value == null) {
throw new NullPointerException("value in a Node is required.");
}
this.value = value;
this.style = style;
this.resolved = resolved;
}
/**
* Get scalar style of this node.
*
* @return
* @see org.elasticsearch.util.yaml.snakeyaml.events.ScalarEvent
* @see http://yaml.org/spec/1.1/#id864487
*/
public Character getStyle() {
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()
+ ")>";
}
}

View File

@ -0,0 +1,75 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.nodes;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
import java.util.List;
/**
* Represents a sequence.
* <p>
* A sequence is a ordered collection of nodes.
* </p>
*/
public class SequenceNode extends CollectionNode {
private Class<? extends Object> listType;
private List<Node> value;
public SequenceNode(Tag tag, boolean resolved, List<Node> value, Mark startMark, Mark endMark,
Boolean flowStyle) {
super(tag, startMark, endMark, flowStyle);
if (value == null) {
throw new NullPointerException("value in a Node is required.");
}
this.value = value;
listType = Object.class;
this.resolved = resolved;
}
public SequenceNode(Tag tag, List<Node> value, Boolean flowStyle) {
this(tag, true, value, null, null, flowStyle);
}
@Override
public NodeId getNodeId() {
return NodeId.sequence;
}
/**
* Returns the elements in this sequence.
*
* @return Nodes in the specified order.
*/
public List<Node> getValue() {
for (Node node : value) {
node.setType(listType);
}
return value;
}
public void setListType(Class<? extends Object> listType) {
this.listType = listType;
}
public String toString() {
return "<" + this.getClass().getName() + " (tag=" + getTag() + ", value=" + getValue()
+ ")>";
}
}

View File

@ -0,0 +1,164 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.nodes;
import org.elasticsearch.util.yaml.snakeyaml.error.YAMLException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.util.*;
public final class Tag implements Comparable<Tag> {
public static final String PREFIX = "tag:yaml.org,2002:";
public static final Tag YAML = new Tag(PREFIX + "yaml");
public static final Tag VALUE = new Tag(PREFIX + "value");
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;
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 = tag;
}
public Tag(Class<? extends Object> clazz) {
if (clazz == null) {
throw new NullPointerException("Class for tag must be provided.");
}
this.value = Tag.PREFIX + clazz.getName();
}
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("Unknown tag: " + value);
}
return value.substring(Tag.PREFIX.length());
}
public int getLength() {
return value.length();
}
@Override
public String toString() {
return value;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj instanceof Tag) {
return value.equals(((Tag) obj).getValue());
} else if (obj instanceof String) {
if (value.equals(obj.toString())) {
// TODO to be removed later (version 2.0?)
System.err.println("Comparing Tag and String is deprecated.");
return true;
}
}
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());
}
public int compareTo(Tag o) {
return value.compareTo(o.getValue());
}
}

View File

@ -0,0 +1,64 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.parser;
import org.elasticsearch.util.yaml.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 org.elasticsearch.util.yaml.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>
*
* @throws ParserException Thrown in case of malformed input.
*/
public Event getEvent();
}

View File

@ -0,0 +1,43 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.parser;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
import org.elasticsearch.util.yaml.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);
}
}

View File

@ -0,0 +1,786 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.parser;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
import org.elasticsearch.util.yaml.snakeyaml.error.YAMLException;
import org.elasticsearch.util.yaml.snakeyaml.events.*;
import org.elasticsearch.util.yaml.snakeyaml.nodes.Tag;
import org.elasticsearch.util.yaml.snakeyaml.reader.StreamReader;
import org.elasticsearch.util.yaml.snakeyaml.scanner.Scanner;
import org.elasticsearch.util.yaml.snakeyaml.scanner.ScannerImpl;
import org.elasticsearch.util.yaml.snakeyaml.tokens.*;
import org.elasticsearch.util.yaml.snakeyaml.util.ArrayStack;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* <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.
*
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public final 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);
}
private final Scanner scanner;
private Event currentEvent;
private List<Integer> yamlVersion;
private Map<String, String> tagHandles;
private final ArrayStack<Production> states;
private final ArrayStack<Mark> marks;
private Production state;
public ParserImpl(StreamReader reader) {
this.scanner = new ScannerImpl(reader);
currentEvent = null;
yamlVersion = null;
tagHandles = new HashMap<String, String>();
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 choices) {
peekEvent();
if (currentEvent != null) {
if (currentEvent.is(choices)) {
return true;
}
}
return false;
}
/*
* 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)) {
tagHandles = 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 {
@SuppressWarnings("unchecked")
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();
List<Object> version_tags = processDirectives();
List<Object> version = (List<Object>) version_tags.get(0);
Map<String, String> tags = (Map<String, String>) version_tags.get(1);
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();
Integer[] versionInteger;
if (version != null) {
versionInteger = new Integer[2];
versionInteger = version.toArray(versionInteger);
} else {
versionInteger = null;
}
event = new DocumentStartEvent(startMark, endMark, true, versionInteger, tags);
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 List<Object> processDirectives() {
yamlVersion = null;
tagHandles = new HashMap<String, String>();
while (scanner.checkToken(Token.ID.Directive)) {
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());
}
yamlVersion = (List<Integer>) token.getValue();
} 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);
}
}
List<Object> value = new ArrayList<Object>(2);
value.add(yamlVersion);
if (!tagHandles.isEmpty()) {
value.add(new HashMap<String, String>(tagHandles));
} else {
value.add(new HashMap<String, String>());
}
for (String key : DEFAULT_TAGS.keySet()) {
if (!tagHandles.containsKey(key)) {
tagHandles.put(key, DEFAULT_TAGS.get(key));
}
}
return value;
}
/**
* <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 (!tagHandles.containsKey(handle)) {
throw new ParserException("while parsing a node", startMark,
"found undefined tag handle " + handle, tagMark);
}
tag = tagHandles.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,
Boolean.FALSE);
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,
Boolean.TRUE);
state = new ParseFlowSequenceFirstEntry();
} else if (scanner.checkToken(Token.ID.FlowMappingStart)) {
endMark = scanner.peekToken().getEndMark();
event = new MappingStartEvent(anchor, tag, implicit, startMark, endMark,
Boolean.TRUE);
state = new ParseFlowMappingFirstKey();
} else if (block && scanner.checkToken(Token.ID.BlockSequenceStart)) {
endMark = scanner.peekToken().getStartMark();
event = new SequenceStartEvent(anchor, tag, implicit, startMark, endMark,
Boolean.FALSE);
state = new ParseBlockSequenceFirstEntry();
} else if (block && scanner.checkToken(Token.ID.BlockMappingStart)) {
endMark = scanner.peekToken().getStartMark();
event = new MappingStartEvent(anchor, tag, implicit, startMark, endMark,
Boolean.FALSE);
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, (char) 0);
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(), Boolean.TRUE);
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, (char) 0);
}
}

View File

@ -0,0 +1,31 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.parser;
import org.elasticsearch.util.yaml.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 http://en.wikipedia.org/wiki/LL_parser
*/
interface Production {
public Event produce();
}

View File

@ -0,0 +1,41 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.reader;
import org.elasticsearch.util.yaml.snakeyaml.error.YAMLException;
public class ReaderException extends YAMLException {
private static final long serialVersionUID = 8710781187529689083L;
private String name;
private char character;
private int position;
public ReaderException(String name, int position, char character, String message) {
super(message);
this.name = name;
this.character = character;
this.position = position;
}
@Override
public String toString() {
return "unacceptable character #" + Integer.toHexString((int) character).toUpperCase()
+ " " + getMessage() + "\nin \"" + name + "\", position " + position;
}
}

View File

@ -0,0 +1,186 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.reader;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
import org.elasticsearch.util.yaml.snakeyaml.error.YAMLException;
import org.elasticsearch.util.yaml.snakeyaml.scanner.Constant;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.Charset;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Reader: checks if characters are in allowed range, adds '\0' to the end.
*
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public class StreamReader {
// NON_PRINTABLE changed from PyYAML: \uFFFD excluded because Java returns
// it in case of data corruption
final static Pattern NON_PRINTABLE = Pattern
.compile("[^\t\n\r\u0020-\u007E\u0085\u00A0-\uD7FF\uE000-\uFFFC]");
private String name;
private final Reader stream;
private int pointer = 0;
private boolean eof = true;
private final StringBuilder buffer;
private int index = 0;
private int line = 0;
private int column = 0;
public StreamReader(String stream) {
this.name = "<string>";
this.buffer = new StringBuilder();
checkPrintable(stream);
this.buffer.append(stream);
this.stream = null;
this.eof = true;
}
public StreamReader(Reader reader) {
this.name = "<reader>";
this.buffer = new StringBuilder();
this.stream = reader;
this.eof = false;
}
void checkPrintable(CharSequence data) {
Matcher em = NON_PRINTABLE.matcher(data);
if (em.find()) {
int position = this.index + this.buffer.length() - this.pointer + em.start();
throw new ReaderException(name, position, em.group().charAt(0),
" special characters are not allowed");
}
}
public Mark getMark() {
return new Mark(name, this.index, this.line, this.column, this.buffer.toString(),
this.pointer);
}
public void forward() {
forward(1);
}
/**
* read the next length characters and move the pointer.
*
* @param length
*/
public void forward(int length) {
if (this.pointer + length + 1 >= this.buffer.length()) {
update(length + 1);
}
char ch = 0;
for (int i = 0; i < length; i++) {
ch = this.buffer.charAt(this.pointer);
this.pointer++;
this.index++;
if (Constant.LINEBR.has(ch) || (ch == '\r' && buffer.charAt(pointer) != '\n')) {
this.line++;
this.column = 0;
} else if (ch != '\uFEFF') {
this.column++;
}
}
}
public char peek() {
return peek(0);
}
/**
* Peek the next index-th character
*
* @param index
* @return
*/
public char peek(int index) {
if (this.pointer + index + 1 > this.buffer.length()) {
update(index + 1);
}
return this.buffer.charAt(this.pointer + index);
}
/**
* peek the next length characters
*
* @param length
* @return
*/
public String prefix(int length) {
if (this.pointer + length >= this.buffer.length()) {
update(length);
}
if (this.pointer + length > this.buffer.length()) {
return this.buffer.substring(this.pointer, this.buffer.length());
} else {
return this.buffer.substring(this.pointer, this.pointer + length);
}
}
private void update(int length) {
this.buffer.delete(0, this.pointer);
this.pointer = 0;
while (this.buffer.length() < length) {
String rawData = null;
if (!this.eof) {
char[] data = new char[1024];
int converted = -2;
try {
converted = this.stream.read(data);
} catch (IOException ioe) {
throw new YAMLException(ioe);
}
if (converted == -1) {
this.eof = true;
} else {
rawData = new String(data, 0, converted);
}
}
if (rawData != null) {
checkPrintable(rawData);
this.buffer.append(rawData);
}
if (this.eof) {
this.buffer.append('\0');
break;
}
}
}
public int getColumn() {
return column;
}
public Charset getEncoding() {
return Charset.forName(((UnicodeReader) this.stream).getEncoding());
}
public int getIndex() {
return index;
}
public int getLine() {
return line;
}
}

View File

@ -0,0 +1,115 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.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.*;
/**
* 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 {
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.
*/
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.
*/
protected void init() throws IOException {
if (internalIn2 != null)
return;
String 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 = "UTF-8";
unread = n - 3;
} else if ((bom[0] == (byte) 0xFE) && (bom[1] == (byte) 0xFF)) {
encoding = "UTF-16BE";
unread = n - 2;
} else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)) {
encoding = "UTF-16LE";
unread = n - 2;
} else {
// Unicode BOM mark not found, unread all bytes
encoding = "UTF-8";
unread = n;
}
if (unread > 0)
internalIn.unread(bom, (n - unread), unread);
// Use given encoding
internalIn2 = new InputStreamReader(internalIn, encoding);
}
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);
}
}

View File

@ -0,0 +1,81 @@
/*
* See LICENSE file in distribution for copyright and licensing information.
*/
package org.yaml.snakeyaml.resolver;
//Source for Ragel 6.3
/**
* Generated by Ragel 6.3 (http://www.complang.org/ragel/)
* @see http://www.complang.org/ragel/
*/
public class RagelMachine {
%%{
machine snakeyaml;
action bool_tag { tag = "tag:yaml.org,2002:bool"; }
action merge_tag { tag = "tag:yaml.org,2002:merge"; }
action null_tag { tag = "tag:yaml.org,2002:null"; }
action value_tag { tag = "tag:yaml.org,2002:value"; }
action int_tag { tag = "tag:yaml.org,2002:int"; }
action float_tag { tag = "tag:yaml.org,2002:float"; }
action timestamp_tag { tag = "tag:yaml.org,2002:timestamp"; }
Bool = ("yes" | "Yes" | "YES" | "no" | "No" | "NO" |
"true" | "True" | "TRUE" | "false" | "False" | "FALSE" |
"on" | "On" | "ON" | "off" | "Off" | "OFF") %/bool_tag;
Merge = "<<" %/merge_tag;
Value = "=" %/value_tag;
Null = ("~" | "null" | "Null" | "NULL" | " ") %/null_tag;
sign = "-" | "+";
digit2 = digit | "_";
binaryInt = "0b" [0-1_]+;
octalInt = "0" [0-7_]+;
decimalInt = "0" | [1-9]digit2* (":" [0-5]? digit)*;
hexaInt = "0x" [0-9a-fA-F_]+;
Int = sign? (binaryInt | octalInt | decimalInt | hexaInt) %/int_tag;
exp = [eE] sign digit+;
Float = ((sign? ((digit+ digit2* "." digit2* exp?)
| ((digit+ digit2*)? "." digit+ digit2* exp?)
| (digit+ (":" [0-5]? digit)+ "." digit*)
| "." ("inf" | "Inf" | "INF")))
| ("." ("nan" | "NaN" | "NAN"))) %/float_tag;
TimestampShort = digit{4} ("-" digit{2}){2} %/timestamp_tag;
fract = "." digit*;
zone = [ \t]* ("Z" | (sign digit{1,2} ( ":" digit{2} )?));
Timestamp = digit{4} ("-" digit{1,2}){2} ([Tt] | [ \t]+)
digit{1,2} ":" digit{2} ":" digit{2} fract? zone? %/timestamp_tag;
Scalar = Bool | Null | Int | Float | TimestampShort | Merge | Value | Timestamp;
main := Scalar;
write data nofinal;
}%%
public String scan(String scalar) {
if (scalar == null) {
throw new NullPointerException("Scalar must be provided.");
}
String tag = null;
int cs = 0;
int p = 0;
int pe = scalar.length();
int eof = pe;
char[] data;
if (pe == 0) {
// NULL value
data = new char[] { '~' };
pe = 1;
eof = 1;
} else {
data = scalar.toCharArray();
}
%%{
# Initialize and execute.
write init;
write exec;
}%%
return tag;
}
}

View File

@ -0,0 +1,147 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.resolver;
import org.elasticsearch.util.yaml.snakeyaml.nodes.NodeId;
import org.elasticsearch.util.yaml.snakeyaml.nodes.Tag;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
/**
* Resolver tries to detect a type by scalars's content (when the type is
* implicit)
*
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
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)$");
public static final Pattern FLOAT = Pattern
.compile("^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?|[-+]?(?:[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>>();
/**
* Create Resolver
*
* @param respectDefaultImplicitScalars false to parse/dump scalars as plain Strings
* @deprecated override addImplicitResolvers instead
*/
public Resolver(boolean respectDefaultImplicitScalars) {
if (respectDefaultImplicitScalars) {
addImplicitResolvers();
}
}
protected void addImplicitResolvers() {
addImplicitResolver(Tag.BOOL, BOOL, "yYnNtTfFoO");
addImplicitResolver(Tag.FLOAT, FLOAT, "-+0123456789.");
addImplicitResolver(Tag.INT, INT, "-+0123456789");
addImplicitResolver(Tag.MERGE, MERGE, "<");
addImplicitResolver(Tag.NULL, NULL, "~nN\0");
addImplicitResolver(Tag.NULL, EMPTY, null);
addImplicitResolver(Tag.TIMESTAMP, TIMESTAMP, "0123456789");
addImplicitResolver(Tag.VALUE, VALUE, "=");
// 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() {
this(true);
}
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 = new Character(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) {
List<ResolverTuple> resolvers = null;
if ("".equals(value)) {
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;
}
}
}

View File

@ -0,0 +1,46 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.resolver;
import org.elasticsearch.util.yaml.snakeyaml.nodes.Tag;
import java.util.regex.Pattern;
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;
}
}

View File

@ -0,0 +1,56 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.scanner;
public final class Constant {
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;
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);
private String content;
private Constant(String content) {
this.content = content;
}
public boolean has(char ch) {
return content.indexOf(ch) != -1;
}
public boolean hasNo(char ch) {
return !has(ch);
}
public boolean has(char ch, String additional) {
return additional.indexOf(ch) != -1 || content.indexOf(ch) != -1;
}
public boolean hasNo(char ch, String additional) {
return !has(ch, additional);
}
}

View File

@ -0,0 +1,64 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.scanner;
import org.elasticsearch.util.yaml.snakeyaml.tokens.Token;
/**
* This interface represents an input stream of {@link Token Tokens}.
* <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 org.elasticsearch.util.yaml.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.
*
* @return The token that will be returned on the next call to
* {@link #getToken}
* @throws ScannerException Thrown in case of malformed input.
*/
Token peekToken();
/**
* Returns the next token.
* <p>
* The token will be removed from the stream.
* </p>
*
* @throws ScannerException Thrown in case of malformed input.
*/
Token getToken();
}

View File

@ -0,0 +1,60 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.scanner;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
import org.elasticsearch.util.yaml.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);
}
}

View File

@ -0,0 +1,77 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.scanner;
import org.elasticsearch.util.yaml.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;
}
}

View File

@ -0,0 +1,47 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
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
protected String getArguments() {
return "value=" + value;
}
@Override
public ID getTokenId() {
return ID.Alias;
}
}

View File

@ -0,0 +1,47 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
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
protected String getArguments() {
return "value=" + value;
}
@Override
public ID getTokenId() {
return ID.Anchor;
}
}

View File

@ -0,0 +1,36 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public final class BlockEndToken extends Token {
public BlockEndToken(Mark startMark, Mark endMark) {
super(startMark, endMark);
}
@Override
public ID getTokenId() {
return ID.BlockEnd;
}
}

View File

@ -0,0 +1,36 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public final class BlockEntryToken extends Token {
public BlockEntryToken(Mark startMark, Mark endMark) {
super(startMark, endMark);
}
@Override
public ID getTokenId() {
return ID.BlockEntry;
}
}

View File

@ -0,0 +1,36 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public final class BlockMappingStartToken extends Token {
public BlockMappingStartToken(Mark startMark, Mark endMark) {
super(startMark, endMark);
}
@Override
public ID getTokenId() {
return ID.BlockMappingStart;
}
}

View File

@ -0,0 +1,36 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public final class BlockSequenceStartToken extends Token {
public BlockSequenceStartToken(Mark startMark, Mark endMark) {
super(startMark, endMark);
}
@Override
public ID getTokenId() {
return ID.BlockSequenceStart;
}
}

View File

@ -0,0 +1,64 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
import org.elasticsearch.util.yaml.snakeyaml.error.YAMLException;
import java.util.List;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
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
protected String getArguments() {
if (value != null) {
return "name=" + name + ", value=[" + value.get(0) + ", " + value.get(1) + "]";
} else {
return "name=" + name;
}
}
@Override
public ID getTokenId() {
return ID.Directive;
}
}

View File

@ -0,0 +1,36 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public final class DocumentEndToken extends Token {
public DocumentEndToken(Mark startMark, Mark endMark) {
super(startMark, endMark);
}
@Override
public ID getTokenId() {
return ID.DocumentEnd;
}
}

View File

@ -0,0 +1,36 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public final class DocumentStartToken extends Token {
public DocumentStartToken(Mark startMark, Mark endMark) {
super(startMark, endMark);
}
@Override
public ID getTokenId() {
return ID.DocumentStart;
}
}

View File

@ -0,0 +1,36 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public final class FlowEntryToken extends Token {
public FlowEntryToken(Mark startMark, Mark endMark) {
super(startMark, endMark);
}
@Override
public ID getTokenId() {
return ID.FlowEntry;
}
}

View File

@ -0,0 +1,36 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public final class FlowMappingEndToken extends Token {
public FlowMappingEndToken(Mark startMark, Mark endMark) {
super(startMark, endMark);
}
@Override
public ID getTokenId() {
return ID.FlowMappingEnd;
}
}

View File

@ -0,0 +1,36 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public final class FlowMappingStartToken extends Token {
public FlowMappingStartToken(Mark startMark, Mark endMark) {
super(startMark, endMark);
}
@Override
public ID getTokenId() {
return ID.FlowMappingStart;
}
}

View File

@ -0,0 +1,36 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public final class FlowSequenceEndToken extends Token {
public FlowSequenceEndToken(Mark startMark, Mark endMark) {
super(startMark, endMark);
}
@Override
public ID getTokenId() {
return ID.FlowSequenceEnd;
}
}

View File

@ -0,0 +1,36 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public final class FlowSequenceStartToken extends Token {
public FlowSequenceStartToken(Mark startMark, Mark endMark) {
super(startMark, endMark);
}
@Override
public ID getTokenId() {
return ID.FlowSequenceStart;
}
}

View File

@ -0,0 +1,36 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public final class KeyToken extends Token {
public KeyToken(Mark startMark, Mark endMark) {
super(startMark, endMark);
}
@Override
public ID getTokenId() {
return ID.Key;
}
}

View File

@ -0,0 +1,63 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public final class ScalarToken extends Token {
private final String value;
private final boolean plain;
private final char style;
public ScalarToken(String value, Mark startMark, Mark endMark, boolean plain) {
this(value, plain, startMark, endMark, (char) 0);
}
public ScalarToken(String value, boolean plain, Mark startMark, Mark endMark, char style) {
super(startMark, endMark);
this.value = value;
this.plain = plain;
this.style = style;
}
public boolean getPlain() {
return this.plain;
}
public String getValue() {
return this.value;
}
public char getStyle() {
return this.style;
}
@Override
protected String getArguments() {
return "value=" + value + ", plain=" + plain + ", style=" + style;
}
@Override
public ID getTokenId() {
return ID.Scalar;
}
}

View File

@ -0,0 +1,36 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public final class StreamEndToken extends Token {
public StreamEndToken(Mark startMark, Mark endMark) {
super(startMark, endMark);
}
@Override
public ID getTokenId() {
return ID.StreamEnd;
}
}

View File

@ -0,0 +1,36 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public final class StreamStartToken extends Token {
public StreamStartToken(Mark startMark, Mark endMark) {
super(startMark, endMark);
}
@Override
public ID getTokenId() {
return ID.StreamStart;
}
}

View File

@ -0,0 +1,47 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public final class TagToken extends Token {
private final TagTuple value;
public TagToken(TagTuple value, Mark startMark, Mark endMark) {
super(startMark, endMark);
this.value = value;
}
public TagTuple getValue() {
return this.value;
}
@Override
protected String getArguments() {
return "value=[" + value.getHandle() + ", " + value.getSuffix() + "]";
}
@Override
public ID getTokenId() {
return ID.Tag;
}
}

View File

@ -0,0 +1,41 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
public final class TagTuple {
private final String handle;
private final String suffix;
public TagTuple(String handle, String suffix) {
if (suffix == null) {
throw new NullPointerException("Suffix must be provided.");
}
this.handle = handle;
this.suffix = suffix;
}
public String getHandle() {
return handle;
}
public String getSuffix() {
return suffix;
}
}

View File

@ -0,0 +1,81 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
import org.elasticsearch.util.yaml.snakeyaml.error.YAMLException;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public abstract class Token {
public enum ID {
Alias, Anchor, BlockEnd, BlockEntry, BlockMappingStart, BlockSequenceStart, Directive, DocumentEnd, DocumentStart, FlowEntry, FlowMappingEnd, FlowMappingStart, FlowSequenceEnd, FlowSequenceStart, Key, Scalar, StreamEnd, StreamStart, Tag, Value
}
private final Mark startMark;
private final Mark endMark;
public Token(Mark startMark, Mark endMark) {
if (startMark == null || endMark == null) {
throw new YAMLException("Token requires marks.");
}
this.startMark = startMark;
this.endMark = endMark;
}
public String toString() {
return "<" + this.getClass().getName() + "(" + getArguments() + ")>";
}
public Mark getStartMark() {
return startMark;
}
public Mark getEndMark() {
return endMark;
}
/**
* @see __repr__ for Token in PyYAML
*/
protected String getArguments() {
return "";
}
/**
* For error reporting.
*
* @see class variable 'id' in PyYAML
*/
public abstract ID getTokenId();
/*
* for tests only
*/
@Override
public boolean equals(Object obj) {
if (obj instanceof Token) {
return toString().equals(obj.toString());
} else {
return false;
}
}
}

View File

@ -0,0 +1,36 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.tokens;
import org.elasticsearch.util.yaml.snakeyaml.error.Mark;
/**
* @see <a href="http://pyyaml.org/wiki/PyYAML">PyYAML</a> for more information
*/
public final class ValueToken extends Token {
public ValueToken(Mark startMark, Mark endMark) {
super(startMark, endMark);
}
@Override
public ID getTokenId() {
return ID.Value;
}
}

View File

@ -0,0 +1,45 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.util;
import java.util.ArrayList;
public class ArrayStack<T> {
private ArrayList<T> stack;
public ArrayStack(int initSize) {
stack = new ArrayList<T>(initSize);
}
public void push(T obj) {
stack.add(obj);
}
public T pop() {
return stack.remove(stack.size() - 1);
}
public boolean isEmpty() {
return stack.isEmpty();
}
public void clear() {
stack.clear();
}
}

View File

@ -0,0 +1,123 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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 org.elasticsearch.util.yaml.snakeyaml.util;
import org.elasticsearch.util.yaml.snakeyaml.error.YAMLException;
public abstract class Base64Coder {
// Mapping table from 6-bit nibbles to Base64 characters.
private final 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 final 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 byte array into Base64 format. No blanks or line breaks are
* inserted.
*
* @param in an array containing the data bytes to be encoded.
* @return A character array with the Base64 encoded data.
*/
public static char[] encode(byte[] in) {
int iLen = in.length;
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 = 0;
int op = 0;
while (ip < iLen) {
int i0 = in[ip++] & 0xff;
int i1 = ip < iLen ? in[ip++] & 0xff : 0;
int i2 = ip < iLen ? 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 Base64 data. No blanks or line breaks are allowed within the
* Base64 encoded 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) {
int iLen = in.length;
if (iLen % 4 != 0)
throw new YAMLException("Length of Base64 encoded input string is not a multiple of 4.");
while (iLen > 0 && in[iLen - 1] == '=')
iLen--;
int oLen = (iLen * 3) / 4;
byte[] out = new byte[oLen];
int ip = 0;
int op = 0;
while (ip < iLen) {
int i0 = in[ip++];
int i1 = in[ip++];
int i2 = ip < iLen ? in[ip++] : 'A';
int i3 = ip < iLen ? in[ip++] : 'A';
if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127)
throw new YAMLException("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 YAMLException("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;
}
}