This is an automated email from the ASF dual-hosted git repository.

radu pushed a commit to branch feature/SLING-9655
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-graphql-core.git


The following commit(s) were added to refs/heads/feature/SLING-9655 by this 
push:
     new 1e4eaf9  SLING-9655 - Caching support for the GraphQL core
1e4eaf9 is described below

commit 1e4eaf9e2ad66225ca051976ba03ce40b1111719
Author: Radu Cotescu <[email protected]>
AuthorDate: Thu Aug 20 19:10:44 2020 +0200

    SLING-9655 - Caching support for the GraphQL core
    
    * exposed GraphQLCacheProvider as a very thin API for supporting
    persisted queries
    * implemented the HTTP API for persisted queries (needs some IT)
---
 .../graphql/api/cache/GraphQLCacheProvider.java    | 54 ++++++++++++++++++++++
 .../sling/graphql/api/cache/package-info.java}     | 16 ++-----
 ...Provider.java => GraphQLCacheProviderImpl.java} | 40 ++++++++++------
 .../sling/graphql/core/servlet/GraphQLServlet.java | 24 +++++++---
 ...Test.java => GraphQLCacheProviderImplTest.java} |  6 +--
 5 files changed, 104 insertions(+), 36 deletions(-)

diff --git 
a/src/main/java/org/apache/sling/graphql/api/cache/GraphQLCacheProvider.java 
b/src/main/java/org/apache/sling/graphql/api/cache/GraphQLCacheProvider.java
new file mode 100644
index 0000000..bab13e0
--- /dev/null
+++ b/src/main/java/org/apache/sling/graphql/api/cache/GraphQLCacheProvider.java
@@ -0,0 +1,54 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.api.cache;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * A {@code GraphQLCacheProvider} is responsible for caching GraphQL queries, 
in order to provide support for persisted queries for the
+ * {@link org.apache.sling.graphql.core.servlet.GraphQLServlet}.
+ */
+@ProviderType
+public interface GraphQLCacheProvider {
+
+    /**
+     * Attempts to retrieve a previously persisted query from the cache.
+     *
+     * @param hash           the query's SHA-256 hash
+     * @param resourceType   the resource type of the {@link 
org.apache.sling.graphql.core.servlet.GraphQLServlet} which will execute the
+     *                       query, since multiple servlets can be registered
+     * @param selectorString the selector string with which the {@link 
org.apache.sling.graphql.core.servlet.GraphQLServlet} is registered
+     * @return the query, if found, {@code null} otherwise
+     * @see #cacheQuery(String, String, String)
+     */
+    @Nullable String getQuery(@NotNull String hash, @NotNull String 
resourceType, @Nullable String selectorString);
+
+    /**
+     * Stores the {@code query} into the cache, potentially overriding a 
previous value.
+     *
+     * @param query          the GraphQL query
+     * @param resourceType   the resource type of the {@link 
org.apache.sling.graphql.core.servlet.GraphQLServlet} which will execute the
+     *                       query, since multiple servlets can be registered
+     * @param selectorString the selector string with which the {@link 
org.apache.sling.graphql.core.servlet.GraphQLServlet} is registered
+     * @return the query's SHA-256 hash, which will be passed to the GraphQL 
client for query retrieval
+     */
+    @NotNull String cacheQuery(@NotNull String query, @NotNull String 
resourceType, @Nullable String selectorString);
+}
diff --git 
a/src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderTest.java
 b/src/main/java/org/apache/sling/graphql/api/cache/package-info.java
similarity index 70%
copy from 
src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderTest.java
copy to src/main/java/org/apache/sling/graphql/api/cache/package-info.java
index 66184b6..25816db 100644
--- 
a/src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderTest.java
+++ b/src/main/java/org/apache/sling/graphql/api/cache/package-info.java
@@ -16,17 +16,7 @@
  ~ specific language governing permissions and limitations
  ~ under the License.
  
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-package org.apache.sling.graphql.core.cache;
+@Version("0.0.1")
+package org.apache.sling.graphql.api.cache;
 
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-public class GraphQLCacheProviderTest {
-
-    @Test
-    public void getHash() throws Exception {
-        GraphQLCacheProvider provider = new GraphQLCacheProvider();
-        
assertEquals("b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9",
 provider.getHash("hello world"));
-    }
-}
+import org.osgi.annotation.versioning.Version;
diff --git 
a/src/main/java/org/apache/sling/graphql/core/cache/GraphQLCacheProvider.java 
b/src/main/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderImpl.java
similarity index 75%
rename from 
src/main/java/org/apache/sling/graphql/core/cache/GraphQLCacheProvider.java
rename to 
src/main/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderImpl.java
index 20afddf..dcfb4ae 100644
--- 
a/src/main/java/org/apache/sling/graphql/core/cache/GraphQLCacheProvider.java
+++ 
b/src/main/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderImpl.java
@@ -29,6 +29,8 @@ import javax.cache.configuration.MutableConfiguration;
 import javax.cache.spi.CachingProvider;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.graphql.api.cache.GraphQLCacheProvider;
+import org.apache.sling.graphql.core.engine.SlingGraphQLException;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.osgi.framework.BundleContext;
@@ -43,9 +45,9 @@ import org.slf4j.LoggerFactory;
 @Component(
         immediate = true
 )
-public class GraphQLCacheProvider {
+public class GraphQLCacheProviderImpl implements GraphQLCacheProvider {
 
-    private static final Logger LOGGER = 
LoggerFactory.getLogger(GraphQLCacheProvider.class);
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(GraphQLCacheProviderImpl.class);
 
     @Reference
     private CachingProvider cachingProvider;
@@ -54,19 +56,24 @@ public class GraphQLCacheProvider {
 
     private ServiceRegistration<GraphQLCacheProvider> registration;
 
+    @Override
     @Nullable
     public String getQuery(@NotNull String hash, @NotNull String resourceType, 
@Nullable String selectorString) {
         return persistedQueriesCache.get(getCacheKey(hash, resourceType, 
selectorString));
     }
 
-    public void cacheQuery(@NotNull String query, @NotNull String 
resourceType, @Nullable String selectorString) {
-        String key = getCacheKey("123", resourceType, selectorString);
+    @Override
+    @NotNull
+    public String cacheQuery(@NotNull String query, @NotNull String 
resourceType, @Nullable String selectorString) {
+        String hash = getHash(query);
+        String key = getCacheKey(hash, resourceType, selectorString);
         persistedQueriesCache.put(key, query);
+        return hash;
     }
 
 
     @Activate
-    public void activate(BundleContext bundleContext) {
+    private void activate(BundleContext bundleContext) {
         if (cachingProvider != null) {
             try {
                 CacheManager cacheManager = cachingProvider.getCacheManager();
@@ -82,7 +89,7 @@ public class GraphQLCacheProvider {
     }
 
     @Deactivate
-    public void deactivate(BundleContext bundleContext) {
+    private void deactivate() {
         if (registration != null) {
             registration.unregister();
         }
@@ -99,16 +106,21 @@ public class GraphQLCacheProvider {
         return key.toString();
     }
 
-    @NotNull String getHash(@NotNull String query) throws 
NoSuchAlgorithmException {
-        MessageDigest digest = MessageDigest.getInstance("SHA-256");
-        byte[] hash = digest.digest(query.getBytes(StandardCharsets.UTF_8));
+    @NotNull String getHash(@NotNull String query) {
         StringBuilder buffer = new StringBuilder();
-        for (int i = 0; i < hash.length; i++) {
-            String hex = Integer.toHexString(0xff & hash[i]);
-            if (hex.length() == 1) {
-                buffer.append('0');
+        try {
+            MessageDigest digest = MessageDigest.getInstance("SHA-256");
+            byte[] hash = 
digest.digest(query.getBytes(StandardCharsets.UTF_8));
+
+            for (byte b : hash) {
+                String hex = Integer.toHexString(0xff & b);
+                if (hex.length() == 1) {
+                    buffer.append('0');
+                }
+                buffer.append(hex);
             }
-            buffer.append(hex);
+        } catch (NoSuchAlgorithmException e) {
+            throw new SlingGraphQLException("Failed hashing query - " + 
e.getMessage());
         }
         return buffer.toString();
     }
diff --git 
a/src/main/java/org/apache/sling/graphql/core/servlet/GraphQLServlet.java 
b/src/main/java/org/apache/sling/graphql/core/servlet/GraphQLServlet.java
index 0daf0ef..25f7928 100644
--- a/src/main/java/org/apache/sling/graphql/core/servlet/GraphQLServlet.java
+++ b/src/main/java/org/apache/sling/graphql/core/servlet/GraphQLServlet.java
@@ -34,7 +34,7 @@ import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.SlingHttpServletResponse;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.servlets.SlingAllMethodsServlet;
-import org.apache.sling.graphql.core.cache.GraphQLCacheProvider;
+import org.apache.sling.graphql.api.cache.GraphQLCacheProvider;
 import org.apache.sling.graphql.core.engine.GraphQLResourceQuery;
 import org.apache.sling.graphql.core.engine.SlingDataFetcherSelector;
 import org.apache.sling.graphql.core.json.JsonSerializer;
@@ -81,8 +81,6 @@ public class GraphQLServlet extends SlingAllMethodsServlet {
     private static final String SUFFIX_PERSISTED = "/persisted";
     private static final Pattern PATTERN_GET_PERSISTED_QUERY = 
Pattern.compile("^" + SUFFIX_PERSISTED + "/([a-f0-9]{64})$");
 
-    private Config config;
-
     @ObjectClassDefinition(
         name = "Apache Sling GraphQL Servlet",
         description = "Servlet that implements GraphQL endpoints")
@@ -145,11 +143,9 @@ public class GraphQLServlet extends SlingAllMethodsServlet 
{
                     } else {
                         response.sendError(HttpServletResponse.SC_NOT_FOUND, 
"Cannot find persisted query " + queryHash);
                     }
-                    return;
                 }
             } else {
                 response.sendError(HttpServletResponse.SC_BAD_REQUEST);
-                return;
             }
         } else {
             execute(request.getResource(), request, response);
@@ -165,7 +161,9 @@ public class GraphQLServlet extends SlingAllMethodsServlet {
                 return;
             }
             String query = IOUtils.toString(request.getInputStream(), 
StandardCharsets.UTF_8);
-            cacheProvider.cacheQuery(query, 
request.getResource().getResourceType(), 
request.getRequestPathInfo().getSelectorString());
+            String hash = cacheProvider.cacheQuery(query, 
request.getResource().getResourceType(),
+                    request.getRequestPathInfo().getSelectorString());
+            response.addHeader("Location", getLocationHeaderValue(request, 
hash));
             response.setStatus(HttpServletResponse.SC_CREATED);
         } else {
             execute(request.getResource(), request, response);
@@ -210,4 +208,18 @@ public class GraphQLServlet extends SlingAllMethodsServlet 
{
         }
     }
 
+    @NotNull
+    private String getLocationHeaderValue(@NotNull SlingHttpServletRequest 
request, @NotNull String hash) {
+        StringBuilder location = new StringBuilder();
+        location.append(request.getScheme()).append("://");
+        location.append(request.getServerName());
+        int localPort = request.getLocalPort();
+        if (localPort != 80 && localPort != 443) {
+            location.append(":").append(localPort);
+        }
+        
location.append(request.getContextPath()).append(request.getPathInfo()).append("/").append(hash);
+        return location.toString();
+    }
+
+
 }
diff --git 
a/src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderTest.java
 
b/src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderImplTest.java
similarity index 88%
rename from 
src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderTest.java
rename to 
src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderImplTest.java
index 66184b6..19c0d3a 100644
--- 
a/src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderTest.java
+++ 
b/src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderImplTest.java
@@ -20,13 +20,13 @@ package org.apache.sling.graphql.core.cache;
 
 import org.junit.Test;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
 
-public class GraphQLCacheProviderTest {
+public class GraphQLCacheProviderImplTest {
 
     @Test
     public void getHash() throws Exception {
-        GraphQLCacheProvider provider = new GraphQLCacheProvider();
+        GraphQLCacheProviderImpl provider = new GraphQLCacheProviderImpl();
         
assertEquals("b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9",
 provider.getHash("hello world"));
     }
 }

Reply via email to