Skip to content

Commit

Permalink
add checks before calling next() when evaluating path segments
Browse files Browse the repository at this point in the history
fixes #1089

(cherry picked from commit a955c63)
  • Loading branch information
Justin Lee committed Dec 14, 2016
1 parent f1de7f3 commit 9fca502
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
* @since 1.3
*/
public class PathTarget {
private final String path;
private final List<String> segments;
private boolean validateNames = true;
private int position;
Expand All @@ -54,6 +55,7 @@ public PathTarget(final Mapper mapper, final MappedClass root, final String path
this.root = root;
segments = asList(path.split("\\."));
this.mapper = mapper;
this.path = path;
}

/**
Expand Down Expand Up @@ -104,6 +106,9 @@ private void resolve() {
String segment = next();

if (segment.equals("$") || segment.matches("[0-9]+")) { // array operator
if (!hasNext()) {
throw new ValidationException("The given path is invalid: " + path);
}
segment = next();
}
field = resolveField(segment);
Expand All @@ -112,7 +117,9 @@ private void resolve() {
if (!field.isMap()) {
translate(field.getNameToStore());
} else {
next(); // consume the map key segment
if (hasNext()) {
next(); // consume the map key segment
}
}
} else {
if (validateNames) {
Expand Down
33 changes: 22 additions & 11 deletions morphia/src/test/java/org/mongodb/morphia/TestUpdateOps.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,14 @@
import org.mongodb.morphia.query.UpdateOpsImpl;
import org.mongodb.morphia.query.UpdateResults;
import org.mongodb.morphia.query.ValidationException;
import org.mongodb.morphia.testmodel.Article;
import org.mongodb.morphia.testmodel.Circle;
import org.mongodb.morphia.testmodel.Rectangle;
import org.mongodb.morphia.testmodel.Translation;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -655,23 +658,31 @@ public void testSetOnInsertWhenUpdating() throws Exception {

@Test
public void testSetUnset() throws Exception {
final Key<Circle> key = getDs().save(new Circle(1));
Datastore ds = getDs();
final Key<Circle> key = ds.save(new Circle(1));

UpdateResults res = getDs().updateFirst(getDs().find(Circle.class).filter("radius", 1D),
getDs().createUpdateOperations(Circle.class).set("radius", 2D));
assertUpdated(ds.updateFirst(ds.find(Circle.class).filter("radius", 1D),
ds.createUpdateOperations(Circle.class).set("radius", 2D)), 1);

assertUpdated(res, 1);
assertThat(ds.getByKey(Circle.class, key).getRadius(), is(2D));

final Circle c = getDs().getByKey(Circle.class, key);
assertThat(c.getRadius(), is(2D));

assertUpdated(ds.updateFirst(ds.find(Circle.class).filter("radius", 2D),
ds.createUpdateOperations(Circle.class).unset("radius")), 1);

res = getDs().updateFirst(getDs().find(Circle.class).filter("radius", 2D),
getDs().createUpdateOperations(Circle.class).unset("radius"));
assertUpdated(res, 1);
assertThat(ds.getByKey(Circle.class, key).getRadius(), is(0D));

Article article = new Article();

ds.save(article);

ds.update(ds.find(Article.class),
ds.createUpdateOperations(Article.class)
.set("translations", new HashMap<String, Translation>()));

final Circle c2 = getDs().getByKey(Circle.class, key);
assertThat(c2.getRadius(), is(0D));
ds.update(ds.find(Article.class),
ds.createUpdateOperations(Article.class)
.unset("translations"));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
import org.mongodb.morphia.mapping.EmbeddedMappingTest.WithNested;
import org.mongodb.morphia.mapping.MappedClass;
import org.mongodb.morphia.mapping.Mapper;
import org.mongodb.morphia.query.ValidationException;
import org.mongodb.morphia.testmodel.Article;

import static org.junit.Assert.fail;

public class PathTargetTest extends TestBase {

Expand Down Expand Up @@ -78,17 +82,33 @@ public void arrays() {
PathTarget pathTarget = new PathTarget(mapper, mappedClass, "listEmbeddedType.1.number");
Assert.assertEquals("listEmbeddedType.1.number", pathTarget.translatedPath());
Assert.assertEquals(mapper.getMappedClass(EmbeddedType.class).getMappedFieldByJavaField("number"), pathTarget.getTarget());

try {
new PathTarget(mapper, mappedClass, "listEmbeddedType.$").translatedPath();
fail("The dangling $ should have failed.");
} catch (ValidationException ignored) {

}

try {
new PathTarget(mapper, mappedClass, "listEmbeddedType.1").translatedPath();
fail("The dangling 1 should have failed.");
} catch (ValidationException ignored) {
}
}

@Test
public void maps() {
getMorphia().map(Student.class);
getMorphia().map(Student.class, Article.class);
Mapper mapper = getMorphia().getMapper();
MappedClass mappedClass = mapper.getMappedClass(Student.class);

final PathTarget pathTarget = new PathTarget(mapper, mappedClass, "grades.$.data.name");
PathTarget pathTarget = new PathTarget(mapper, mappedClass, "grades.$.data.name");
Assert.assertEquals("grades.$.data.name", pathTarget.translatedPath());
Assert.assertEquals(mapper.getMappedClass(Grade.class).getMappedFieldByJavaField("data"), pathTarget.getTarget());

pathTarget = new PathTarget(mapper, mapper.getMappedClass(Article.class), "translations");
Assert.assertEquals("translations", pathTarget.translatedPath());
}

@Test
Expand Down

0 comments on commit 9fca502

Please sign in to comment.