This is an automated email from the ASF dual-hosted git repository.
bdelacretaz pushed a commit to branch master
in repository
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-graphql-schema-aggregator.git
The following commit(s) were added to refs/heads/master by this push:
new d842942 SLING-10620 - validate section names
d842942 is described below
commit d842942b2b23227ad39daf844639cf5a52c04de2
Author: Bertrand Delacretaz <[email protected]>
AuthorDate: Fri Jul 16 11:08:29 2021 +0200
SLING-10620 - validate section names
---
.../aggregator/impl/DefaultSchemaAggregator.java | 24 ++++++------
.../graphql/schema/aggregator/impl/Partial.java | 13 ++++++-
.../schema/aggregator/impl/PartialConstants.java | 28 --------------
.../schema/aggregator/impl/PartialReader.java | 45 ++++++++++++++--------
.../schema/aggregator/impl/CapitalizeTest.java | 15 ++------
.../schema/aggregator/impl/PartialReaderTest.java | 24 ++++++++----
.../aggregator/impl/ProviderBundleTrackerTest.java | 4 +-
.../partials/duplicate.section.partial.txt | 4 +-
src/test/resources/partials/example.partial.txt | 4 +-
9 files changed, 76 insertions(+), 85 deletions(-)
diff --git
a/src/main/java/org/apache/sling/graphql/schema/aggregator/impl/DefaultSchemaAggregator.java
b/src/main/java/org/apache/sling/graphql/schema/aggregator/impl/DefaultSchemaAggregator.java
index 8942b20..0f83f41 100644
---
a/src/main/java/org/apache/sling/graphql/schema/aggregator/impl/DefaultSchemaAggregator.java
+++
b/src/main/java/org/apache/sling/graphql/schema/aggregator/impl/DefaultSchemaAggregator.java
@@ -37,11 +37,6 @@ import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import static
org.apache.sling.graphql.schema.aggregator.impl.PartialConstants.S_MUTATION;
-import static
org.apache.sling.graphql.schema.aggregator.impl.PartialConstants.S_PROLOGUE;
-import static
org.apache.sling.graphql.schema.aggregator.impl.PartialConstants.S_QUERY;
-import static
org.apache.sling.graphql.schema.aggregator.impl.PartialConstants.S_TYPES;
-
@Component(service = SchemaAggregator.class)
public class DefaultSchemaAggregator implements SchemaAggregator {
private static final Logger log =
LoggerFactory.getLogger(DefaultSchemaAggregator.class.getName());
@@ -50,17 +45,20 @@ public class DefaultSchemaAggregator implements
SchemaAggregator {
@Reference
private ProviderBundleTracker tracker;
- static String capitalize(String s) {
- if(s == null) {
+ static String capitalize(Partial.SectionName name) {
+ if(name == null) {
return null;
- } else if(s.length() > 1) {
+ }
+
+ final String s = name.toString();
+ if(s.length() > 1) {
return String.format("%s%s", s.substring(0, 1).toUpperCase(),
s.substring(1).toLowerCase());
} else {
return s.toUpperCase();
}
}
- private void copySection(Set<Partial> selected, String sectionName,
boolean inBlock, Writer target) throws IOException {
+ private void copySection(Set<Partial> selected, Partial.SectionName
sectionName, boolean inBlock, Writer target) throws IOException {
String prefixToWrite = inBlock ? String.format("%ntype %s {%n",
capitalize(sectionName)) : null;
boolean anyOutput = false;
for(Partial p : selected) {
@@ -103,10 +101,10 @@ public class DefaultSchemaAggregator implements
SchemaAggregator {
}
// copy sections that belong in the output SDL
- copySection(selected, S_PROLOGUE, false, target);
- copySection(selected, S_QUERY, true, target);
- copySection(selected, S_MUTATION, true, target);
- copySection(selected, S_TYPES, false, target);
+ copySection(selected, Partial.SectionName.PROLOGUE, false, target);
+ copySection(selected, Partial.SectionName.QUERY, true, target);
+ copySection(selected, Partial.SectionName.MUTATION, true, target);
+ copySection(selected, Partial.SectionName.TYPES, false, target);
final StringBuilder partialNames = new StringBuilder();
selected.forEach(p -> {
diff --git
a/src/main/java/org/apache/sling/graphql/schema/aggregator/impl/Partial.java
b/src/main/java/org/apache/sling/graphql/schema/aggregator/impl/Partial.java
index 9b3d418..21f02e5 100644
--- a/src/main/java/org/apache/sling/graphql/schema/aggregator/impl/Partial.java
+++ b/src/main/java/org/apache/sling/graphql/schema/aggregator/impl/Partial.java
@@ -31,16 +31,25 @@ import java.util.Set;
interface Partial {
/** A section in the partial */
interface Section {
- String getName();
+ SectionName getName();
String getDescription();
Reader getContent() throws IOException;
}
+ enum SectionName {
+ PARTIAL,
+ REQUIRES,
+ PROLOGUE,
+ QUERY,
+ MUTATION,
+ TYPES
+ };
+
/** The name of this partial */
String getName();
/** Return a specific section of the partial, by name */
- Optional<Section> getSection(String name);
+ Optional<Section> getSection(SectionName name);
/** Names of the Partials on which this one depends */
Set<String> getRequiredPartialNames();
diff --git
a/src/main/java/org/apache/sling/graphql/schema/aggregator/impl/PartialConstants.java
b/src/main/java/org/apache/sling/graphql/schema/aggregator/impl/PartialConstants.java
deleted file mode 100644
index aac50b2..0000000
---
a/src/main/java/org/apache/sling/graphql/schema/aggregator/impl/PartialConstants.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF 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.apache.sling.graphql.schema.aggregator.impl;
-
-class PartialConstants {
- public static final String S_PARTIAL = "PARTIAL";
- public static final String S_REQUIRES = "REQUIRES";
- public static final String S_PROLOGUE = "PROLOGUE";
- public static final String S_TYPES = "TYPES";
- public static final String S_MUTATION = "MUTATION";
- public static final String S_QUERY = "QUERY";
-}
\ No newline at end of file
diff --git
a/src/main/java/org/apache/sling/graphql/schema/aggregator/impl/PartialReader.java
b/src/main/java/org/apache/sling/graphql/schema/aggregator/impl/PartialReader.java
index 783a9d3..b7fcea0 100644
---
a/src/main/java/org/apache/sling/graphql/schema/aggregator/impl/PartialReader.java
+++
b/src/main/java/org/apache/sling/graphql/schema/aggregator/impl/PartialReader.java
@@ -21,7 +21,7 @@ package org.apache.sling.graphql.schema.aggregator.impl;
import java.io.IOException;
import java.io.Reader;
import java.util.Collections;
-import java.util.HashMap;
+import java.util.EnumMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
@@ -31,7 +31,6 @@ import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.BoundedReader;
/** Reader for the partials format, which parses a partial file and
@@ -43,7 +42,7 @@ class PartialReader implements Partial {
private static final Pattern SECTION_LINE = Pattern.compile("([A-Z]+)
*:(.*)");
private static final int EOL = '\n';
- private final Map<String, Section> sections = new HashMap<>();
+ private final Map<SectionName, Section> sections = new
EnumMap<>(SectionName.class);
private final String name;
private final Set<String> requiredPartialNames;
@@ -58,12 +57,12 @@ class PartialReader implements Partial {
static class ParsedSection implements Partial.Section {
private final Supplier<Reader> sectionSource;
- private final String name;
+ private final SectionName name;
private final String description;
private final int startCharIndex;
private final int endCharIndex;
- ParsedSection(Supplier<Reader> sectionSource, String name, String
description, int start, int end) {
+ ParsedSection(Supplier<Reader> sectionSource, SectionName name, String
description, int start, int end) {
this.sectionSource = sectionSource;
this.name = name;
this.description = description;
@@ -72,7 +71,7 @@ class PartialReader implements Partial {
}
@Override
- public String getName() {
+ public SectionName getName() {
return name;
}
@@ -92,7 +91,7 @@ class PartialReader implements Partial {
PartialReader(String name, Supplier<Reader> source) throws IOException {
this.name = name;
parse(source);
- final Partial.Section requirements =
sections.get(PartialConstants.S_REQUIRES);
+ final Partial.Section requirements =
sections.get(SectionName.REQUIRES);
if(requirements == null) {
requiredPartialNames = Collections.emptySet();
} else {
@@ -123,7 +122,7 @@ class PartialReader implements Partial {
final Matcher m = SECTION_LINE.matcher(line);
if(m.matches()) {
// Add previous section
- addSectionIfNameIsSet(source, sectionName,
sectionDescription, lastSectionStart, charCount - line.length());
+ addSectionIfNameIsSet(source, toSectionName(sectionName),
sectionDescription, lastSectionStart, charCount - line.length());
// And setup for the new section
sectionName = m.group(1).trim();
sectionDescription = m.group(2).trim();
@@ -137,26 +136,38 @@ class PartialReader implements Partial {
}
// Add last section
- addSectionIfNameIsSet(source, sectionName, sectionDescription,
lastSectionStart, Integer.MAX_VALUE);
+ addSectionIfNameIsSet(source, toSectionName(sectionName),
sectionDescription, lastSectionStart, Integer.MAX_VALUE);
// And validate
- if(!sections.containsKey(PARTIAL_SECTION)) {
+ if(!sections.containsKey(SectionName.PARTIAL)) {
throw new SyntaxException(String.format("Missing required %s
section", PARTIAL_SECTION));
}
}
- private void addSectionIfNameIsSet(Supplier<Reader> sectionSource, String
name, String description, int start, int end) throws SyntaxException {
- if(name != null) {
- if(sections.containsKey(name)) {
- throw new SyntaxException(String.format("Duplicate section
%s", name));
- }
- sections.put(name, new ParsedSection(sectionSource, name,
description, start, end));
+ private void addSectionIfNameIsSet(Supplier<Reader> sectionSource,
SectionName name, String description, int start, int end) throws
SyntaxException {
+ if(name == null) {
+ return;
+ }
+ if(sections.containsKey(name)) {
+ throw new SyntaxException(String.format("Duplicate section '%s'",
name));
+ }
+ sections.put(name, new ParsedSection(sectionSource, name, description,
start, end));
+ }
+
+ private SectionName toSectionName(String str) throws SyntaxException {
+ if(str == null) {
+ return null;
+ }
+ try {
+ return SectionName.valueOf(str);
+ } catch(Exception e) {
+ throw new SyntaxException(String.format("Invalid section name
'%s'", str));
}
}
@Override
- public Optional<Section> getSection(String name) {
+ public Optional<Section> getSection(Partial.SectionName name) {
final Section s = sections.get(name);
return s == null ? Optional.empty() : Optional.of(s);
}
diff --git
a/src/test/java/org/apache/sling/graphql/schema/aggregator/impl/CapitalizeTest.java
b/src/test/java/org/apache/sling/graphql/schema/aggregator/impl/CapitalizeTest.java
index aaca60d..9e418f0 100644
---
a/src/test/java/org/apache/sling/graphql/schema/aggregator/impl/CapitalizeTest.java
+++
b/src/test/java/org/apache/sling/graphql/schema/aggregator/impl/CapitalizeTest.java
@@ -20,24 +20,17 @@ package org.apache.sling.graphql.schema.aggregator.impl;
import static org.junit.Assert.assertEquals;
+import org.apache.sling.graphql.schema.aggregator.impl.Partial.SectionName;
import org.junit.Test;
public class CapitalizeTest {
@Test
- public void normalStrings() throws Exception {
- assertEquals("Voici", DefaultSchemaAggregator.capitalize("voici"));
- assertEquals("Ou bien", DefaultSchemaAggregator.capitalize("OU BIEN"));
+ public void normalValue() throws Exception {
+ assertEquals("Partial",
DefaultSchemaAggregator.capitalize(SectionName.PARTIAL));
}
@Test
- public void emptyStrings() throws Exception {
- assertEquals("", DefaultSchemaAggregator.capitalize(""));
+ public void emptyValue() throws Exception {
assertEquals(null, DefaultSchemaAggregator.capitalize(null));
}
-
- @Test
- public void shortStrings() throws Exception {
- assertEquals("A", DefaultSchemaAggregator.capitalize("a"));
- assertEquals("B", DefaultSchemaAggregator.capitalize("B"));
- }
}
\ No newline at end of file
diff --git
a/src/test/java/org/apache/sling/graphql/schema/aggregator/impl/PartialReaderTest.java
b/src/test/java/org/apache/sling/graphql/schema/aggregator/impl/PartialReaderTest.java
index 737f9e1..a7863cf 100644
---
a/src/test/java/org/apache/sling/graphql/schema/aggregator/impl/PartialReaderTest.java
+++
b/src/test/java/org/apache/sling/graphql/schema/aggregator/impl/PartialReaderTest.java
@@ -22,14 +22,11 @@ import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
import java.io.IOException;
import java.io.InputStream;
@@ -38,7 +35,7 @@ import java.util.function.Supplier;
import java.util.regex.Pattern;
import org.apache.commons.io.IOUtils;
-import org.apache.sling.graphql.schema.aggregator.U;
+import org.apache.sling.graphql.schema.aggregator.impl.Partial.SectionName;
import org.junit.Test;
public class PartialReaderTest {
@@ -46,7 +43,7 @@ public class PartialReaderTest {
private static final String NONAME = "<NO NAME>";
private void assertSection(Partial p, String name, String description,
String contentRegexp) throws IOException {
- final Optional<Partial.Section> os = p.getSection(name);
+ final Optional<Partial.Section> os =
p.getSection(SectionName.valueOf(name));
assertTrue("Expecting section " + name, os.isPresent());
final Partial.Section s = os.get();
if(description != null) {
@@ -84,7 +81,7 @@ public class PartialReaderTest {
public void parseExample() throws Exception {
final PartialReader p = new PartialReader(NONAME,
getResourceReaderSupplier("/partials/example.partial.txt"));
assertSection(p, "PARTIAL", "Example GraphQL schema partial", "The
contents.*PARTIAL.*PARTIAL.*PARTIAL.*equired section\\.");
- assertSection(p, "REQUIRE", "base.scalars, base.schema", null);
+ assertSection(p, "REQUIRES", "base.scalars, base.schema", null);
assertSection(p, "PROLOGUE", "", "The prologue content.*the aggregated
schema.*other sections\\.");
assertSection(p, "QUERY", "", "The optional query sections of all
partials are aggregated in a query \\{\\} section in the output\\.");
assertSection(p, "MUTATION", "", "The optional mutation sections of
all partials are aggregated in a mutation \\{\\} section in the output\\.");
@@ -111,19 +108,30 @@ public class PartialReaderTest {
}
@Test
+ public void invalidSectionName() throws Exception {
+ final String invalidName = "REQUIRE";
+ final Exception e = assertThrows(
+ PartialReader.SyntaxException.class,
+ () -> new PartialReader(NONAME,
getStringReaderSupplier(String.format("PARTIAL:test\n%s:something\n",
invalidName)))
+ );
+ final String expected = "Invalid section name 'REQUIRE'";
+ assertTrue(String.format("Expected %s in %s", expected,
e.getMessage()), e.getMessage().contains(expected));
+ }
+
+ @Test
public void duplicateSection() throws Exception {
final Exception e = assertThrows(
PartialReader.SyntaxException.class,
() -> new PartialReader(NONAME,
getResourceReaderSupplier("/partials/duplicate.section.partial.txt"))
);
- final String expected = "Duplicate section DUPLICATE";
+ final String expected = "Duplicate section 'QUERY'";
assertTrue(String.format("Expected %s in %s", expected,
e.getMessage()), e.getMessage().contains(expected));
}
@Test
public void requires() throws Exception {
final PartialReader p = new PartialReader(NONAME,
getResourceReaderSupplier("/partials/c.sdl.txt"));
- assertTrue("Expecting requires section",
p.getSection(PartialConstants.S_REQUIRES).isPresent());
+ assertTrue("Expecting requires section",
p.getSection(Partial.SectionName.REQUIRES).isPresent());
assertEquals("[a.sdl, b.sdl]", p.getRequiredPartialNames().toString());
}
}
\ No newline at end of file
diff --git
a/src/test/java/org/apache/sling/graphql/schema/aggregator/impl/ProviderBundleTrackerTest.java
b/src/test/java/org/apache/sling/graphql/schema/aggregator/impl/ProviderBundleTrackerTest.java
index 7a82e7a..1f78d9b 100644
---
a/src/test/java/org/apache/sling/graphql/schema/aggregator/impl/ProviderBundleTrackerTest.java
+++
b/src/test/java/org/apache/sling/graphql/schema/aggregator/impl/ProviderBundleTrackerTest.java
@@ -87,7 +87,7 @@ public class ProviderBundleTrackerTest {
assertEquals(2, tracker.getSchemaProviders().size());
}
- private void assertSectionContent(Partial p, String name, String expected)
throws IOException {
+ private void assertSectionContent(Partial p, Partial.SectionName name,
String expected) throws IOException {
final Optional<Partial.Section> os = p.getSection(name);
assertTrue("Expecting section " + name, os.isPresent());
assertEquals(expected, IOUtils.toString(os.get().getContent()).trim());
@@ -98,6 +98,6 @@ public class ProviderBundleTrackerTest {
final Bundle a = U.mockProviderBundle(bundleContext, "A", ++bundleId,
"1.txt");
tracker.addingBundle(a, null);
final Partial p =
tracker.getSchemaProviders().values().iterator().next();
- assertSectionContent(p, PartialConstants.S_QUERY, "Fake query for
1.txt");
+ assertSectionContent(p, Partial.SectionName.QUERY, "Fake query for
1.txt");
}
}
diff --git a/src/test/resources/partials/duplicate.section.partial.txt
b/src/test/resources/partials/duplicate.section.partial.txt
index f92e311..81f1d04 100644
--- a/src/test/resources/partials/duplicate.section.partial.txt
+++ b/src/test/resources/partials/duplicate.section.partial.txt
@@ -1,6 +1,6 @@
PARTIAL: some description
-DUPLICATE: will be provided twice
+QUERY: will be provided twice
-DUPLICATE: here's the second one
+QUERY: here's the second one
And the last line, required for correct parsing
\ No newline at end of file
diff --git a/src/test/resources/partials/example.partial.txt
b/src/test/resources/partials/example.partial.txt
index 4c76c53..eddcf3e 100644
--- a/src/test/resources/partials/example.partial.txt
+++ b/src/test/resources/partials/example.partial.txt
@@ -8,8 +8,8 @@ The contents of the PARTIAL section are not included in the
output.
The text that follows PARTIAL is a description of this partial.
PARTIAL is the only required section.
-REQUIRE: base.scalars, base.schema
-The REQUIRE section indicates partials which are required for this
+REQUIRES: base.scalars, base.schema
+The REQUIRES section indicates partials which are required for this
one to be valid. Its contents are not included in the output.
PROLOGUE: