Skip to content

Commit

Permalink
Merge pull request #329 from adobe/dev
Browse files Browse the repository at this point in the history
Sync dev to main before release
  • Loading branch information
LSantha authored Jun 28, 2024
2 parents 0debfdd + 241831c commit 5404a15
Show file tree
Hide file tree
Showing 22 changed files with 982 additions and 218 deletions.
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ version: 2.1

orbs:
codecov: codecov/codecov@1.1.1
browser-tools: circleci/browser-tools@1.2.4
browser-tools: circleci/browser-tools@1.4.4

common:
integration_test_steps: &integration_test_steps
steps:
- checkout
- browser-tools/install-browser-tools:
chrome-version: 114.0.5735.90 # TODO: remove -> https://github.com/CircleCI-Public/browser-tools-orb/issues/75
chrome-version: 116.0.5845.96 # TODO: remove -> https://github.com/CircleCI-Public/browser-tools-orb/issues/75
- restore_cache:
keys:
- maven-repo-{{ .Environment.CACHE_VERSION }}-its-{{ arch }}-{{ .Branch }}-{{ checksum "pom.xml" }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,5 @@ PassEnv DISP_ID
</IfModule>

ErrorDocument 404 ${404_PAGE}
</VirtualHost>
ErrorDocument 503 ${503_PAGE}
</VirtualHost>
1 change: 1 addition & 0 deletions classic/dispatcher/src/conf.d/variables/ams_default.vars
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Define ASSET_DOWNLOAD_RULE deny
# Customer specific values
Define CONTENT_FOLDER_NAME venia
Define 404_PAGE /content/venia/us/en/errors/404.html
Define 503_PAGE /content/venia/us/en/errors/503.html

#Enable/Disable 3DMime type. Enabling default by setting to 1
Define 3D_MIMETYPE_ENABLED 1
69 changes: 65 additions & 4 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,34 @@ Import-Package: javax.annotation;version=0.0.0,*
</build>

<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.jcr</groupId>
<artifactId>jcr</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>osgi.cmpn</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
Expand Down Expand Up @@ -163,6 +191,12 @@ Import-Package: javax.annotation;version=0.0.0,*
<artifactId>magento-graphql</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>osgi.core</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.adobe.cq</groupId>
<artifactId>core.wcm.components.core</artifactId>
Expand All @@ -172,7 +206,7 @@ Import-Package: javax.annotation;version=0.0.0,*
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.api</artifactId>
<scope>provided</scope>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
Expand All @@ -197,6 +231,14 @@ Import-Package: javax.annotation;version=0.0.0,*
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.2</version>
<scope>test</scope>
</dependency>
<!-- Mockito dependencies -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
<dependency>
Expand All @@ -213,13 +255,32 @@ Import-Package: javax.annotation;version=0.0.0,*
<!-- required to provide the transitive dependencies of aem-mock -->
<groupId>com.adobe.aem</groupId>
<artifactId>uber-jar</artifactId>
<version>6.4.4</version>
<classifier>apis</classifier>
<scope>test</scope>
<version>${uber.jar.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.wcm</groupId>
<artifactId>io.wcm.testing.aem-mock.junit5</artifactId>
<version>5.5.0</version>
<scope>test</scope>
</dependency>
<!-- Sling Mock JUnit 5 -->
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.testing.sling-mock.junit5</artifactId>
<version>3.5.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ public String getId() {
@Override
public ComponentData getData() {
final ComponentData data = ((Component) searchResults).getData();
if (data == null) {
return null;
}

final AtomicReference<ComponentData> dataRef = new AtomicReference<>();
ComponentData componentData = (ComponentData) Proxy.newProxyInstance(this.getClass().getClassLoader(),
new Class[]{ComponentData.class}, (proxy, method, args) -> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ Copyright 2021 Adobe
~
~ Licensed 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 com.venia.core.models.commerce.services;

import com.adobe.cq.commerce.core.components.models.product.Product;
import com.adobe.cq.commerce.core.components.models.productlist.ProductList;
import com.drew.lang.annotations.Nullable;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.factory.ModelFactory;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;

/**
* This service allows to traverse a {@link Resource} tree looking for a {@link Resource} of a set of particular resource types and if
* found adapting them to given adapter type. This helps for example finding the product component on the page and return the Product model
* from it.
*/
@Component(
service = com.venia.core.models.commerce.services.CommerceComponentModelFinder.class)
public class CommerceComponentModelFinder {

private static final Logger LOGGER = LoggerFactory.getLogger(com.venia.core.models.commerce.services.CommerceComponentModelFinder.class);
private static final Collection<String> PRODUCT_RTS = Collections.singleton("core/cif/components/commerce/product/v1/product");
private static final Collection<String> PRODUCT_LIST_RTS = Arrays.asList(
"core/cif/components/commerce/productlist/v2/productlist",
"core/cif/components/commerce/productlist/v1/productlist");

@Reference
private ModelFactory modelFactory;

@Nullable
public Product findProductComponentModel(SlingHttpServletRequest request, Resource root) {
return findComponentModel(request, root, PRODUCT_RTS, Product.class);
}

@Nullable
public ProductList findProductListComponentModel(SlingHttpServletRequest request, Resource root) {
return findComponentModel(request, root, PRODUCT_LIST_RTS, ProductList.class);
}

@Nullable
public <T> T findComponentModel(SlingHttpServletRequest request, Resource root, Collection<String> resourceTypes,
Class<T> adapterType) {
Resource componentResource = findChildResourceWithType(root, resourceTypes);
if (componentResource != null) {
return modelFactory.getModelFromWrappedRequest(request, componentResource, adapterType);
} else {
return null;
}
}

private Resource findChildResourceWithType(Resource fromResource, Collection<String> resourceTypes) {
if (fromResource == null) {
return null;
}

LOGGER.debug("Looking for child resource type '{}' from {}", resourceTypes, fromResource.getPath());

for (Resource child : fromResource.getChildren()) {
for (String resourceType : resourceTypes) {
if (child.isResourceType(resourceType)) {
LOGGER.debug("Found child resource type '{}' at {}", resourceType, child.getPath());
return child;
}
}

Resource resource = findChildResourceWithType(child, resourceTypes);
if (resource != null) {
return resource;
}
}

return null;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package com.venia.core.models.commerce.servlets;

import com.adobe.cq.commerce.core.components.models.common.SiteStructure;
import com.adobe.cq.commerce.core.components.models.product.Product;
import com.adobe.cq.commerce.core.components.models.productlist.ProductList;
import com.adobe.cq.commerce.core.components.models.retriever.AbstractCategoryRetriever;
import com.adobe.cq.commerce.core.components.models.retriever.AbstractProductRetriever;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import com.day.cq.wcm.api.PageManagerFactory;
import com.venia.core.models.commerce.services.CommerceComponentModelFinder;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.scripting.SlingBindings;
import org.apache.sling.scripting.core.ScriptHelper;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component(
service = {Filter.class},
property = {
"sling.filter.scope=REQUEST",
"sling.filter.resourceTypes=cq:Page",
"sling.filter.resourceTypes=core/cif/components/structure/page/v1/page",
"sling.filter.resourceTypes=core/cif/components/structure/page/v2/page",
"sling.filter.resourceTypes=core/cif/components/structure/page/v3/page",
"sling.filter.extensions=html",
"sling.filter.extensions=json",
"sling.filter.resource.pattern=/content(/.+)?",
"service.ranking:Integer=-4000"
})
public class CatalogPageErrorFilter implements Filter {
private static final Logger LOGGER = LoggerFactory.getLogger(CatalogPageErrorFilter.class);

@Reference
private PageManagerFactory pageManagerFactory;

@Reference
private CommerceComponentModelFinder commerceModelFinder;

public CatalogPageErrorFilter() {
}

private BundleContext bundleContext;

@Activate
protected void activate(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}

public void init(FilterConfig filterConfig) throws ServletException {
}

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
if (servletRequest instanceof SlingHttpServletRequest && servletResponse instanceof SlingHttpServletResponse) {
SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) servletRequest;
SlingHttpServletResponse slingResponse = (SlingHttpServletResponse) servletResponse;
PageManager pageManager = pageManagerFactory.getPageManager(slingRequest.getResourceResolver());
Page currentPage = pageManager.getContainingPage(slingRequest.getResource());
boolean removeSlingScriptHelperFromBindings = false;
if (currentPage != null) {
// Get the SiteStructure model
SiteStructure siteStructure = slingRequest.adaptTo(SiteStructure.class);
if (siteStructure.isProductPage(currentPage)) {
// add the SlingScriptHelper to the bindings if it is not there yet
removeSlingScriptHelperFromBindings = addSlingScriptHelperIfNeeded(slingRequest, slingResponse);
Product product = commerceModelFinder.findProductComponentModel(slingRequest, currentPage.getContentResource());
if (product != null) {
AbstractProductRetriever productRetriever = product.getProductRetriever();
// force GraphQL query execution
if (productRetriever != null && !product.getFound() && productRetriever.hasErrors()) {
slingResponse.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "Commerce application not reachable");
return;
}
}
} else if (siteStructure.isCategoryPage(currentPage)) {
// add the SlingScriptHelper to the bindings if it is not there yet
removeSlingScriptHelperFromBindings = addSlingScriptHelperIfNeeded(slingRequest, slingResponse);
ProductList productList = commerceModelFinder.findProductListComponentModel(slingRequest, currentPage.getContentResource());
if (productList != null) {
// Get the AbstractCategoryRetriever model
AbstractCategoryRetriever categoryRetriever = productList.getCategoryRetriever();
if ((categoryRetriever != null &&
// force GraphQL query execution for category
categoryRetriever.fetchCategory() == null && categoryRetriever.hasErrors()) ||
// force GraphQL query execution for products
productList.getSearchResultsSet().hasErrors()) {
slingResponse.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "Commerce application not reachable");
return;
}
}
}
if (removeSlingScriptHelperFromBindings) {
// remove the ScriptHelper if we added it before
SlingBindings slingBindings = getSlingBindings(slingRequest);
if (slingBindings != null) {
slingBindings.remove("sling");
}
}
}
}
filterChain.doFilter(servletRequest, servletResponse);
}

public void destroy() {
}

/**
* The {@link com.venia.core.models.commerce.services.CommerceComponentModelFinder} uses
* {@link org.apache.sling.models.factory.ModelFactory#getModelFromWrappedRequest(SlingHttpServletRequest, Resource, Class)}
* to obtain the model of either {@link Product} or {@link ProductList}. That method invokes all
* {@link org.apache.sling.scripting.api.BindingsValuesProvider}
* while creating the wrapped request. In AEM 6.5 they are not executed lazily and depend on some existing bindings on construction of
* which one requires the SlingScriptHelper.
*
* @param slingRequest
*/
private boolean addSlingScriptHelperIfNeeded(SlingHttpServletRequest slingRequest, SlingHttpServletResponse slingResponse) {
SlingBindings slingBindings = getSlingBindings(slingRequest);
if (slingBindings != null && slingBindings.getSling() == null) {
slingBindings.put("sling", new ScriptHelper(bundleContext, null, slingRequest, slingResponse));
return true;
}
return false;
}

private static SlingBindings getSlingBindings(SlingHttpServletRequest slingRequest) {
Object attr = slingRequest.getAttribute(SlingBindings.class.getName());
if (attr == null) {
attr = new SlingBindings();
slingRequest.setAttribute(SlingBindings.class.getName(), attr);
}
return attr instanceof SlingBindings ? (SlingBindings) attr : null;
}
}
Loading

0 comments on commit 5404a15

Please sign in to comment.