diff --git a/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java b/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java index 2f68003cc4288..403162cf7fc90 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java @@ -100,33 +100,36 @@ private ParsedDocument innerParseDocument(SourceToParse source) throws MapperPar context.reset(parser, new ParseContext.Document(), source); // will result in START_OBJECT - int countDownTokens = 0; XContentParser.Token token = parser.nextToken(); if (token != XContentParser.Token.START_OBJECT) { throw new MapperParsingException("Malformed content, must start with an object"); } - boolean emptyDoc = false; - token = parser.nextToken(); - if (token == XContentParser.Token.END_OBJECT) { - // empty doc, we can handle it... - emptyDoc = true; - } else if (token != XContentParser.Token.FIELD_NAME) { - throw new MapperParsingException("Malformed content, after first object, either the type field or the actual properties should exist"); - } - - for (MetadataFieldMapper metadataMapper : mapping.metadataMappers) { - metadataMapper.preParse(context); - } + if (mapping.root.isEnabled()) { + boolean emptyDoc = false; + token = parser.nextToken(); + if (token == XContentParser.Token.END_OBJECT) { + // empty doc, we can handle it... + emptyDoc = true; + } else if (token != XContentParser.Token.FIELD_NAME) { + throw new MapperParsingException("Malformed content, after first object, either the type field or the actual properties should exist"); + } - if (!emptyDoc) { - Mapper update = parseObject(context, mapping.root); - if (update != null) { - context.addDynamicMappingsUpdate(update); + for (MetadataFieldMapper metadataMapper : mapping.metadataMappers) { + metadataMapper.preParse(context); + } + if (emptyDoc == false) { + Mapper update = parseObject(context, mapping.root); + if (update != null) { + context.addDynamicMappingsUpdate(update); + } + } + for (MetadataFieldMapper metadataMapper : mapping.metadataMappers) { + metadataMapper.postParse(context); } - } - for (int i = 0; i < countDownTokens; i++) { - parser.nextToken(); + } else { + // entire type is disabled + parser.skipChildren(); } // try to parse the next token, this should be null if the object is ended properly @@ -135,12 +138,11 @@ private ParsedDocument innerParseDocument(SourceToParse source) throws MapperPar && source.parser() == null && parser != null) { // only check for end of tokens if we created the parser here token = parser.nextToken(); - assert token == null; // double check, in tests, that we didn't end parsing early + if (token != null) { + throw new IllegalArgumentException("Malformed content, found extra data after parsing: " + token); + } } - for (MetadataFieldMapper metadataMapper : mapping.metadataMappers) { - metadataMapper.postParse(context); - } } catch (Throwable e) { // if its already a mapper parsing exception, no need to wrap it... if (e instanceof MapperParsingException) { diff --git a/core/src/test/java/org/elasticsearch/index/mapper/DocumentParserTests.java b/core/src/test/java/org/elasticsearch/index/mapper/DocumentParserTests.java new file mode 100644 index 0000000000000..454f8e814d4da --- /dev/null +++ b/core/src/test/java/org/elasticsearch/index/mapper/DocumentParserTests.java @@ -0,0 +1,64 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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.index.mapper; + +import org.elasticsearch.common.bytes.BytesArray; +import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.json.JsonXContent; +import org.elasticsearch.common.xcontent.json.JsonXContentParser; +import org.elasticsearch.test.ESSingleNodeTestCase; + +// TODO: make this a real unit test +public class DocumentParserTests extends ESSingleNodeTestCase { + + public void testTypeDisabled() throws Exception { + DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); + String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .field("enabled", false).endObject().endObject().string(); + DocumentMapper mapper = mapperParser.parse(mapping); + + BytesReference bytes = XContentFactory.jsonBuilder() + .startObject() + .field("field", "1234") + .endObject().bytes(); + ParsedDocument doc = mapper.parse("test", "type", "1", bytes); + assertNull(doc.rootDoc().getField("field")); + } + + public void testFieldDisabled() throws Exception { + DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); + String mapping = XContentFactory.jsonBuilder().startObject().startObject("type").startObject("properties") + .startObject("foo").field("enabled", false).endObject() + .startObject("bar").field("type", "integer").endObject() + .endObject().endObject().endObject().string(); + DocumentMapper mapper = mapperParser.parse(mapping); + + BytesReference bytes = XContentFactory.jsonBuilder() + .startObject() + .field("foo", "1234") + .field("bar", 10) + .endObject().bytes(); + ParsedDocument doc = mapper.parse("test", "type", "1", bytes); + assertNull(doc.rootDoc().getField("foo")); + assertNotNull(doc.rootDoc().getField("bar")); + } +}