Skip to content

Commit e78bbbf

Browse files
committed
add CBOR data format support
1 parent 68bc785 commit e78bbbf

File tree

9 files changed

+469
-1
lines changed

9 files changed

+469
-1
lines changed

pom.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,13 @@
232232
<scope>compile</scope>
233233
</dependency>
234234

235+
<dependency>
236+
<groupId>com.fasterxml.jackson.dataformat</groupId>
237+
<artifactId>jackson-dataformat-cbor</artifactId>
238+
<version>2.3.2</version>
239+
<scope>compile</scope>
240+
</dependency>
241+
235242
<dependency>
236243
<groupId>io.netty</groupId>
237244
<artifactId>netty</artifactId>
@@ -554,6 +561,7 @@
554561
<include>com.fasterxml.jackson.core:jackson-core</include>
555562
<include>com.fasterxml.jackson.dataformat:jackson-dataformat-smile</include>
556563
<include>com.fasterxml.jackson.dataformat:jackson-dataformat-yaml</include>
564+
<include>com.fasterxml.jackson.dataformat:jackson-dataformat-cbor</include>
557565
<include>joda-time:joda-time</include>
558566
<include>org.joda:joda-convert</include>
559567
<include>io.netty:netty</include>

src/main/java/org/elasticsearch/common/xcontent/XContentFactory.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@
1919

2020
package org.elasticsearch.common.xcontent;
2121

22+
import com.fasterxml.jackson.dataformat.cbor.CBORConstants;
2223
import com.fasterxml.jackson.dataformat.smile.SmileConstants;
2324
import org.elasticsearch.ElasticsearchIllegalArgumentException;
2425
import org.elasticsearch.ElasticsearchParseException;
2526
import org.elasticsearch.common.bytes.BytesArray;
2627
import org.elasticsearch.common.bytes.BytesReference;
28+
import org.elasticsearch.common.xcontent.cbor.CborXContent;
2729
import org.elasticsearch.common.xcontent.json.JsonXContent;
2830
import org.elasticsearch.common.xcontent.smile.SmileXContent;
2931
import org.elasticsearch.common.xcontent.yaml.YamlXContent;
@@ -82,6 +84,20 @@ public static XContentBuilder yamlBuilder(OutputStream os) throws IOException {
8284
return new XContentBuilder(YamlXContent.yamlXContent, os);
8385
}
8486

87+
/**
88+
* Returns a content builder using CBOR format ({@link org.elasticsearch.common.xcontent.XContentType#CBOR}.
89+
*/
90+
public static XContentBuilder cborBuilder() throws IOException {
91+
return contentBuilder(XContentType.CBOR);
92+
}
93+
94+
/**
95+
* Constructs a new cbor builder that will output the result into the provided output stream.
96+
*/
97+
public static XContentBuilder cborBuilder(OutputStream os) throws IOException {
98+
return new XContentBuilder(CborXContent.cborXContent, os);
99+
}
100+
85101
/**
86102
* Constructs a xcontent builder that will output the result into the provided output stream.
87103
*/
@@ -92,6 +108,8 @@ public static XContentBuilder contentBuilder(XContentType type, OutputStream out
92108
return smileBuilder(outputStream);
93109
} else if (type == XContentType.YAML) {
94110
return yamlBuilder(outputStream);
111+
} else if (type == XContentType.CBOR) {
112+
return cborBuilder(outputStream);
95113
}
96114
throw new ElasticsearchIllegalArgumentException("No matching content type for " + type);
97115
}
@@ -106,6 +124,8 @@ public static XContentBuilder contentBuilder(XContentType type) throws IOExcepti
106124
return SmileXContent.contentBuilder();
107125
} else if (type == XContentType.YAML) {
108126
return YamlXContent.contentBuilder();
127+
} else if (type == XContentType.CBOR) {
128+
return CborXContent.contentBuilder();
109129
}
110130
throw new ElasticsearchIllegalArgumentException("No matching content type for " + type);
111131
}
@@ -137,6 +157,8 @@ public static XContentType xContentType(CharSequence content) {
137157
return XContentType.YAML;
138158
}
139159

160+
// CBOR is not supported
161+
140162
for (int i = 0; i < length; i++) {
141163
char c = content.charAt(i);
142164
if (c == '{') {
@@ -209,6 +231,9 @@ public static XContentType xContentType(InputStream si) throws IOException {
209231
return XContentType.YAML;
210232
}
211233
}
234+
if (first == (CBORConstants.BYTE_OBJECT_INDEFINITE & 0xff)){
235+
return XContentType.CBOR;
236+
}
212237
for (int i = 2; i < GUESS_HEADER_LENGTH; i++) {
213238
int val = si.read();
214239
if (val == -1) {
@@ -254,6 +279,9 @@ public static XContentType xContentType(BytesReference bytes) {
254279
if (length > 2 && first == '-' && bytes.get(1) == '-' && bytes.get(2) == '-') {
255280
return XContentType.YAML;
256281
}
282+
if (first == CBORConstants.BYTE_OBJECT_INDEFINITE){
283+
return XContentType.CBOR;
284+
}
257285
for (int i = 0; i < length; i++) {
258286
if (bytes.get(i) == '{') {
259287
return XContentType.JSON;

src/main/java/org/elasticsearch/common/xcontent/XContentType.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
package org.elasticsearch.common.xcontent;
2121

22+
import org.elasticsearch.common.xcontent.cbor.CborXContent;
2223
import org.elasticsearch.common.xcontent.json.JsonXContent;
2324
import org.elasticsearch.common.xcontent.smile.SmileXContent;
2425
import org.elasticsearch.common.xcontent.yaml.YamlXContent;
@@ -84,7 +85,26 @@ public String shortName() {
8485
public XContent xContent() {
8586
return YamlXContent.yamlXContent;
8687
}
87-
};
88+
},
89+
/**
90+
* A CBOR based content type.
91+
*/
92+
CBOR(3) {
93+
@Override
94+
public String restContentType() {
95+
return "application/cbor";
96+
}
97+
98+
@Override
99+
public String shortName() {
100+
return "cbor";
101+
}
102+
103+
@Override
104+
public XContent xContent() {
105+
return CborXContent.cborXContent;
106+
}
107+
},;
88108

89109
public static XContentType fromRestContentType(String contentType) {
90110
if (contentType == null) {
@@ -102,6 +122,10 @@ public static XContentType fromRestContentType(String contentType) {
102122
return YAML;
103123
}
104124

125+
if ("application/cbor".equals(contentType) || "cbor".equalsIgnoreCase(contentType)) {
126+
return CBOR;
127+
}
128+
105129
return null;
106130
}
107131

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.common.xcontent.cbor;
21+
22+
import com.fasterxml.jackson.core.JsonEncoding;
23+
import com.fasterxml.jackson.dataformat.cbor.CBORFactory;
24+
import org.elasticsearch.ElasticsearchParseException;
25+
import org.elasticsearch.common.bytes.BytesReference;
26+
import org.elasticsearch.common.io.FastStringReader;
27+
import org.elasticsearch.common.xcontent.*;
28+
29+
import java.io.*;
30+
31+
/**
32+
* A CBOR based content implementation using Jackson.
33+
*/
34+
public class CborXContent implements XContent {
35+
36+
public static XContentBuilder contentBuilder() throws IOException {
37+
return XContentBuilder.builder(cborXContent);
38+
}
39+
40+
final static CBORFactory cborFactory;
41+
public final static CborXContent cborXContent;
42+
43+
static {
44+
cborFactory = new CBORFactory();
45+
cborXContent = new CborXContent();
46+
}
47+
48+
private CborXContent() {
49+
}
50+
51+
@Override
52+
public XContentType type() {
53+
return XContentType.CBOR;
54+
}
55+
56+
@Override
57+
public byte streamSeparator() {
58+
throw new ElasticsearchParseException("cbor does not support stream parsing...");
59+
}
60+
61+
@Override
62+
public XContentGenerator createGenerator(OutputStream os) throws IOException {
63+
return new CborXContentGenerator(cborFactory.createGenerator(os, JsonEncoding.UTF8));
64+
}
65+
66+
@Override
67+
public XContentGenerator createGenerator(Writer writer) throws IOException {
68+
return new CborXContentGenerator(cborFactory.createGenerator(writer));
69+
}
70+
71+
@Override
72+
public XContentParser createParser(String content) throws IOException {
73+
return new CborXContentParser(cborFactory.createParser(new FastStringReader(content)));
74+
}
75+
76+
@Override
77+
public XContentParser createParser(InputStream is) throws IOException {
78+
return new CborXContentParser(cborFactory.createParser(is));
79+
}
80+
81+
@Override
82+
public XContentParser createParser(byte[] data) throws IOException {
83+
return new CborXContentParser(cborFactory.createParser(data));
84+
}
85+
86+
@Override
87+
public XContentParser createParser(byte[] data, int offset, int length) throws IOException {
88+
return new CborXContentParser(cborFactory.createParser(data, offset, length));
89+
}
90+
91+
@Override
92+
public XContentParser createParser(BytesReference bytes) throws IOException {
93+
if (bytes.hasArray()) {
94+
return createParser(bytes.array(), bytes.arrayOffset(), bytes.length());
95+
}
96+
return createParser(bytes.streamInput());
97+
}
98+
99+
@Override
100+
public XContentParser createParser(Reader reader) throws IOException {
101+
return new CborXContentParser(cborFactory.createParser(reader));
102+
}
103+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.common.xcontent.cbor;
21+
22+
import com.fasterxml.jackson.core.JsonGenerator;
23+
import com.fasterxml.jackson.dataformat.cbor.CBORParser;
24+
import org.elasticsearch.common.bytes.BytesReference;
25+
import org.elasticsearch.common.xcontent.XContentType;
26+
import org.elasticsearch.common.xcontent.json.JsonXContentGenerator;
27+
28+
import java.io.IOException;
29+
import java.io.InputStream;
30+
import java.io.OutputStream;
31+
32+
/**
33+
*
34+
*/
35+
public class CborXContentGenerator extends JsonXContentGenerator {
36+
37+
public CborXContentGenerator(JsonGenerator generator) {
38+
super(generator);
39+
}
40+
41+
@Override
42+
public XContentType contentType() {
43+
return XContentType.CBOR;
44+
}
45+
46+
@Override
47+
public void usePrintLineFeedAtEnd() {
48+
// nothing here
49+
}
50+
51+
@Override
52+
public void writeRawField(String fieldName, InputStream content, OutputStream bos) throws IOException {
53+
writeFieldName(fieldName);
54+
try (CBORParser parser = CborXContent.cborFactory.createParser(content)) {
55+
parser.nextToken();
56+
generator.copyCurrentStructure(parser);
57+
}
58+
}
59+
60+
@Override
61+
public void writeRawField(String fieldName, byte[] content, OutputStream bos) throws IOException {
62+
writeFieldName(fieldName);
63+
try (CBORParser parser = CborXContent.cborFactory.createParser(content)) {
64+
parser.nextToken();
65+
generator.copyCurrentStructure(parser);
66+
}
67+
}
68+
69+
@Override
70+
protected void writeObjectRaw(String fieldName, BytesReference content, OutputStream bos) throws IOException {
71+
writeFieldName(fieldName);
72+
CBORParser parser;
73+
if (content.hasArray()) {
74+
parser = CborXContent.cborFactory.createParser(content.array(), content.arrayOffset(), content.length());
75+
} else {
76+
parser = CborXContent.cborFactory.createParser(content.streamInput());
77+
}
78+
try {
79+
parser.nextToken();
80+
generator.copyCurrentStructure(parser);
81+
} finally {
82+
parser.close();
83+
}
84+
}
85+
86+
@Override
87+
public void writeRawField(String fieldName, byte[] content, int offset, int length, OutputStream bos) throws IOException {
88+
writeFieldName(fieldName);
89+
try (CBORParser parser = CborXContent.cborFactory.createParser(content, offset, length)) {
90+
parser.nextToken();
91+
generator.copyCurrentStructure(parser);
92+
}
93+
}
94+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.common.xcontent.cbor;
21+
22+
import com.fasterxml.jackson.core.JsonParser;
23+
import org.elasticsearch.common.xcontent.XContentType;
24+
import org.elasticsearch.common.xcontent.json.JsonXContentParser;
25+
26+
/**
27+
*
28+
*/
29+
public class CborXContentParser extends JsonXContentParser {
30+
31+
public CborXContentParser(JsonParser parser) {
32+
super(parser);
33+
}
34+
35+
@Override
36+
public XContentType contentType() {
37+
return XContentType.CBOR;
38+
}
39+
}

0 commit comments

Comments
 (0)