├── core-customize ├── .java-version ├── dependencies │ └── .gitkeep ├── manifest.json ├── bootstrap │ ├── config-template │ │ ├── cloud │ │ │ ├── aspect │ │ │ │ ├── backoffice.properties │ │ │ │ ├── api.properties │ │ │ │ ├── accstorefront.properties │ │ │ │ ├── backgroundprocessing.properties │ │ │ │ └── admin.properties │ │ │ ├── persona │ │ │ │ └── development.properties │ │ │ ├── local-dev.properties │ │ │ └── common.properties │ │ ├── local-config │ │ │ └── 99-local.properties │ │ └── localextensions.xml │ ├── demo │ │ ├── config-extras │ │ │ ├── cloud │ │ │ │ └── common.properties │ │ │ └── localextensions.xml │ │ └── manifest.jsonnet.patch │ ├── essentialdata-smartedit-configuration.impex │ └── manifest.jsonnet ├── hybris │ └── bin │ │ └── custom │ │ └── extras │ │ └── modelt │ │ ├── project.properties │ │ ├── src │ │ └── de │ │ │ └── hybris │ │ │ └── platform │ │ │ └── modelt │ │ │ ├── readinesscheck │ │ │ ├── ReadinessCheck.java │ │ │ ├── ReadinessStatus.java │ │ │ ├── ReadinessCheckService.java │ │ │ ├── PerformableReadinessCheck.java │ │ │ ├── impl │ │ │ │ └── DefaultReadinessCheckService.java │ │ │ └── ReadinessCheckResult.java │ │ │ └── constants │ │ │ └── ModeltConstants.java │ │ ├── web │ │ ├── webroot │ │ │ ├── WEB-INF │ │ │ │ ├── lib │ │ │ │ │ └── javax.servlet.jsp.jstl-1.2.5.jar │ │ │ │ ├── ibm-web-ext.xmi │ │ │ │ ├── external-dependencies.xml │ │ │ │ ├── config │ │ │ │ │ ├── modelt-web-app-config.xml │ │ │ │ │ ├── modelt-spring-mvc-config.xml │ │ │ │ │ └── modelt-spring-security-config.xml │ │ │ │ └── web.xml │ │ │ ├── 404.jsp │ │ │ ├── 405.jsp │ │ │ └── 500.jsp │ │ └── src │ │ │ └── de │ │ │ └── hybris │ │ │ └── platform │ │ │ └── modelt │ │ │ └── controller │ │ │ └── ModeltReadinessController.java │ │ ├── .gitignore │ │ ├── README.md │ │ ├── extensioninfo.disabled │ │ ├── .classpath │ │ ├── .project │ │ ├── resources │ │ └── modelt-spring.xml │ │ └── .settings │ │ ├── org.eclipse.jdt.ui.prefs │ │ └── org.eclipse.jdt.core.prefs ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── manifest-to-localextensions.sh ├── manifest-to-properties.sh ├── .gitignore ├── gradle.properties ├── bootstrap-extras.gradle.kts ├── gradlew.bat ├── bootstrap-demo.gradle.kts ├── README.md ├── gradlew ├── build.gradle.kts └── bootstrap.gradle.kts ├── js-storefront ├── .gitignore ├── bootstrap │ └── .vscode │ │ ├── extensions.json │ │ └── settings.json ├── README.md └── bootstrap.sh ├── docker-compose.yml ├── README.md └── docker-resources ├── db_init.sql └── configure-db.sh /core-customize/.java-version: -------------------------------------------------------------------------------- 1 | 17.0 2 | -------------------------------------------------------------------------------- /core-customize/dependencies/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /js-storefront/.gitignore: -------------------------------------------------------------------------------- 1 | # Node Environment 2 | .node-version 3 | -------------------------------------------------------------------------------- /core-customize/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "commerceSuiteVersion": "2211.23" 3 | } 4 | -------------------------------------------------------------------------------- /core-customize/bootstrap/config-template/cloud/aspect/backoffice.properties: -------------------------------------------------------------------------------- 1 | # cloud/aspect/backoffice.properties 2 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/project.properties: -------------------------------------------------------------------------------- 1 | modelt.application-context=modelt-spring.xml 2 | -------------------------------------------------------------------------------- /core-customize/bootstrap/config-template/local-config/99-local.properties: -------------------------------------------------------------------------------- 1 | # put all properties specific to your local setup here 2 | -------------------------------------------------------------------------------- /core-customize/bootstrap/config-template/cloud/aspect/api.properties: -------------------------------------------------------------------------------- 1 | # cloud/aspect/api.properties 2 | 3 | xss.filter.header.X-Frame-Options= 4 | -------------------------------------------------------------------------------- /core-customize/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sap-commerce-tools/ccv2-project-template/HEAD/core-customize/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /core-customize/bootstrap/config-template/cloud/aspect/accstorefront.properties: -------------------------------------------------------------------------------- 1 | # cloud/aspect/accstorefront.properties 2 | 3 | spring.session.enabled=false 4 | xss.filter.header.X-Frame-Options= 5 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/src/de/hybris/platform/modelt/readinesscheck/ReadinessCheck.java: -------------------------------------------------------------------------------- 1 | package de.hybris.platform.modelt.readinesscheck; 2 | 3 | public interface ReadinessCheck { 4 | ReadinessCheckResult getResult(); 5 | } 6 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/src/de/hybris/platform/modelt/readinesscheck/ReadinessStatus.java: -------------------------------------------------------------------------------- 1 | package de.hybris.platform.modelt.readinesscheck; 2 | 3 | public enum ReadinessStatus { 4 | READY, 5 | NOT_READY, 6 | ERROR 7 | } 8 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/src/de/hybris/platform/modelt/readinesscheck/ReadinessCheckService.java: -------------------------------------------------------------------------------- 1 | package de.hybris.platform.modelt.readinesscheck; 2 | 3 | public interface ReadinessCheckService { 4 | ReadinessCheckResult checkReadiness(); 5 | } 6 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/web/webroot/WEB-INF/lib/javax.servlet.jsp.jstl-1.2.5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sap-commerce-tools/ccv2-project-template/HEAD/core-customize/hybris/bin/custom/extras/modelt/web/webroot/WEB-INF/lib/javax.servlet.jsp.jstl-1.2.5.jar -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/web/webroot/404.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 404 Not Found 6 | 7 | 8 |
9 |

404 Not Found

10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /core-customize/bootstrap/config-template/cloud/aspect/backgroundprocessing.properties: -------------------------------------------------------------------------------- 1 | # cloud/aspect/backgroundprocessing.properties 2 | 3 | cluster.node.groups=integration,yHotfolderCandidate,backgroundProcessing 4 | # make sure to set the nodeGroup property of your jobs/cronjobs to backgroundProcessing! 5 | -------------------------------------------------------------------------------- /core-customize/bootstrap/config-template/cloud/aspect/admin.properties: -------------------------------------------------------------------------------- 1 | # cloud/aspect/admin.properties 2 | 3 | system.unlocking.disabled=false 4 | 5 | backoffice.fill.typefacade.cache.on.startup=false 6 | backoffice.solr.search.index.autoinit=false 7 | commerceservices.org.unit.path.generation.enabled=false 8 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/web/webroot/405.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 404 Method not allowed 6 | 7 | 8 |
9 |

404 Method not allowed

10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /core-customize/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/web/webroot/500.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 500 Server Runtime Exception 6 | 7 | 8 |
9 |

404 Server Runtime Exception

10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /core-customize/bootstrap/config-template/cloud/persona/development.properties: -------------------------------------------------------------------------------- 1 | # cloud/persona/development.properties 2 | 3 | # Mock Payment provider 4 | sop.post.url=${ccv2.services.api.url.0}/acceleratorservices/sop-mock/process 5 | # Anybody should be able to access mock payment provider 6 | corsfilter.acceleratorservices.allowedOrigins=* 7 | -------------------------------------------------------------------------------- /core-customize/bootstrap/demo/config-extras/cloud/common.properties: -------------------------------------------------------------------------------- 1 | ######################### 2 | #### DEMO PROPERTIES #### 3 | ######################### 4 | 5 | recaptcha.publickey=TODO 6 | recaptcha.privatekey=TODO 7 | googleApiKey=TODO 8 | 9 | website.electronics-spa.http=${ccv2.services.jsapps.url.0} 10 | website.electronics-spa.https=${ccv2.services.jsapps.url.0} 11 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/src/de/hybris/platform/modelt/readinesscheck/PerformableReadinessCheck.java: -------------------------------------------------------------------------------- 1 | package de.hybris.platform.modelt.readinesscheck; 2 | /** 3 | * Helper interface to make your readiness check "performable". 4 | */ 5 | public interface PerformableReadinessCheck extends ReadinessCheck 6 | { 7 | boolean isEnabled(); 8 | void perform(); 9 | } 10 | -------------------------------------------------------------------------------- /js-storefront/bootstrap/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | // Angular Language Service 4 | "Angular.ng-template", 5 | // Debugger for Chrome 6 | "msjsdiag.debugger-for-chrome", 7 | // The ng lint command uses TSLint under the hood. 8 | "ms-vscode.vscode-typescript-tslint-plugin", 9 | // Prettier - Code formatter 10 | "esbenp.prettier-vscode" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/.gitignore: -------------------------------------------------------------------------------- 1 | #generated by platform build artifacts 2 | *Generated*Constants.java 3 | *Generated*Manager.java 4 | items.xsd 5 | beans.xsd 6 | extensioninfo.xsd 7 | ruleset.xml 8 | platformhome.properties 9 | *testclasses.xml 10 | build.xml 11 | gensrc 12 | eclipsebin 13 | velocity.log 14 | 15 | *_bof.jar 16 | 17 | classes 18 | testclasses 19 | 20 | 21 | extensioninfo.xml 22 | -------------------------------------------------------------------------------- /js-storefront/bootstrap/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // Prettier uses single quotes. 3 | "prettier.singleQuote": true, 4 | // Prettify on save 5 | "editor.formatOnSave": true, 6 | // prettier uses 2 spaces instead of 4 7 | "editor.tabSize": 2, 8 | // organize imports on save 9 | "editor.codeActionsOnSave": { 10 | "source.organizeImports": true 11 | }, 12 | // Uses the project specific typescript version. 13 | "typescript.tsdk": "node_modules/typescript/lib" 14 | } 15 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/README.md: -------------------------------------------------------------------------------- 1 | # modelt Mock Extensions 2 | 3 | Mock extension based on [Preparing a Mock Extension to Deploy Locally][mock] 4 | 5 | [mock]: https://help.sap.com/viewer/b2f400d4c0414461a4bb7e115dccd779/LATEST/en-US/784f9480cf064d3b81af9cad5739fecc.html 6 | 7 | To enable it for local development, rename the file `extensioninfo.disabled` 8 | to `extensioninfo.xml`. 9 | 10 | **Never commit `extensioninfo.xml`, otherwise you will break your project in CCv2!** 11 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/src/de/hybris/platform/modelt/constants/ModeltConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2020 SAP SE or an SAP affiliate company. All rights reserved. 4 | */ 5 | package de.hybris.platform.modelt.constants; 6 | 7 | @SuppressWarnings({"deprecation","squid:CallToDeprecatedMethod"}) 8 | public class ModeltConstants extends GeneratedModeltConstants 9 | { 10 | public static final String EXTENSIONNAME = "modelt"; 11 | 12 | private ModeltConstants() 13 | { 14 | //empty 15 | } 16 | 17 | 18 | } 19 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/web/webroot/WEB-INF/ibm-web-ext.xmi: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /core-customize/manifest-to-localextensions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Extract extensions from a manifest.json to use them in localextensions.xml 4 | 5 | # REQUIRES: jq - https://stedolan.github.io/jq/ 6 | 7 | MANIFEST_FILE=${1:-manifest.json} 8 | 9 | #get extension list 10 | echo '' 11 | echo '---------------localextensions.xml-------------------' 12 | echo '' 13 | extensions=$(jq ".extensions[]" "$MANIFEST_FILE") 14 | for extension in $extensions 15 | do 16 | echo "" 17 | done 18 | 19 | echo '' 20 | echo "--------------------------${ENVIRONMENT}.properties--------------------------" 21 | echo '' 22 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | mssql: 5 | image: "mcr.microsoft.com/mssql/server:2019-latest" 6 | ports: 7 | - "1433:1433" 8 | environment: 9 | - SA_PASSWORD=localSAPassw0rd 10 | - ACCEPT_EULA=ok 11 | mssqlinit: 12 | image: "mcr.microsoft.com/mssql-tools" 13 | volumes: 14 | - ./docker-resources:/tmp/resources 15 | command: bash -c "set -e; cd /tmp/resources && bash configure-db.sh" 16 | environment: 17 | - SQLSERVER=mssql 18 | - SA_PASSWORD=localSAPassw0rd 19 | depends_on: 20 | - mssql 21 | azurite: 22 | image: mcr.microsoft.com/azure-storage/azurite 23 | ports: 24 | - 10000:10000 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CCv2 Template Repository 2 | 3 | - Best-practice setup 4 | - Based on SAP Commerce 2211 5 | - Generates B2C accelerator modules, OCC extension and OCC tests extension 6 | - Includes Spartacus storefront 7 | - Fully automated setup for local development 8 | - [docker-compose](https://docs.docker.com/compose/)-based setup for: 9 | - MS SQL 10 | - [Azurite](https://github.com/Azure/Azurite) (for cloud hotfolder) 11 | 12 | ## How To 13 | 14 | - Clone/Download/Fork this repository 15 | - Follow the steps in the READMEs linked below 16 | 17 | ## SAP Commerce Setup 18 | 19 | [core-customize/README.md](core-customize/README.md) 20 | 21 | ## Spartacus Setup 22 | 23 | [js-storefront/README.md](js-storefront/README.md) 24 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/extensioninfo.disabled: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/web/webroot/WEB-INF/external-dependencies.xml: -------------------------------------------------------------------------------- 1 | 4 | 6 | 4.0.0 7 | de.hybris.platform.modelt 8 | modelt-web 9 | 2011.0 10 | 11 | jar 12 | 13 | 14 | 15 | org.glassfish.web 16 | javax.servlet.jsp.jstl 17 | 1.2.5 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /docker-resources/db_init.sql: -------------------------------------------------------------------------------- 1 | EXEC sp_configure 'show advanced options', 1; 2 | GO 3 | RECONFIGURE 4 | GO 5 | EXEC sp_configure 'cost threshold for parallelism', 50; 6 | EXEC sp_configure 'max degree of parallelism', 4; 7 | EXEC sp_configure 'contained database authentication', 1; 8 | GO 9 | RECONFIGURE 10 | GO 11 | USE master; 12 | GO 13 | IF DB_ID (N'localdev') IS NULL 14 | BEGIN 15 | CREATE DATABASE localdev CONTAINMENT = PARTIAL; 16 | ALTER DATABASE localdev SET READ_COMMITTED_SNAPSHOT ON; 17 | ALTER DATABASE localdev SET ALLOW_SNAPSHOT_ISOLATION ON; 18 | END 19 | ELSE 20 | BEGIN 21 | PRINT N'DB localdev already exists'; 22 | END 23 | GO 24 | USE localdev; 25 | GO 26 | IF DATABASE_PRINCIPAL_ID(N'localdev') IS NULL 27 | BEGIN 28 | CREATE USER localdev WITH PASSWORD = 'localdev1!'; 29 | END 30 | ELSE 31 | BEGIN 32 | PRINT N'user localdev already exists'; 33 | END 34 | GO 35 | EXEC sp_addrolemember 'db_owner', 'localdev'; 36 | GO 37 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | modelt 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.ui.externaltools.ExternalToolBuilder 10 | auto,full, 11 | 12 | 13 | LaunchConfigHandle 14 | <project>/.externalToolBuilders/HybrisCodeGeneration.launch 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | org.springframework.ide.eclipse.core.springbuilder 25 | 26 | 27 | 28 | 29 | 30 | org.springframework.ide.eclipse.core.springnature 31 | org.eclipse.jdt.core.javanature 32 | 33 | 34 | -------------------------------------------------------------------------------- /core-customize/bootstrap/essentialdata-smartedit-configuration.impex: -------------------------------------------------------------------------------- 1 | # ref. 2 | # https://help.sap.com/viewer/d0224eca81e249cb821f2cdf45a82ace/LATEST/en-US/8beedbec8669101491c4a5cd1ffc4465.html 3 | # https://sap.github.io/spartacus-docs/smartEdit-setup-instructions-for-spartacus/#configuring-smartedit-to-work-with-spartacus-32-or-newer 4 | 5 | # Import config properties into impex macros 6 | UPDATE GenericItem[processor=de.hybris.platform.commerceservices.impex.impl.ConfigPropertyImportProcessor];pk[unique=true] 7 | 8 | # TODO: adapt the previewUrl of your cms site 9 | # $storeFront=$config-ccv2.services.accstorefront.url.0 10 | # $jsApp=$config-ccv2.services.jsapps.url.0 11 | # UPDATE CMSSite;uid[unique=true];previewURL; 12 | # ;electronics;$storeFront/?site=electronics 13 | # ;electronics-spa;$jsApp 14 | 15 | # TODO: update Smartedit allowlist 16 | # Default: local dev and storefronts on CCv2 using the default urls 17 | # whitelisting entries support regex 18 | INSERT_UPDATE SmartEditConfiguration;key[unique=true];value 19 | ;whiteListedStorefronts;"[ 20 | ""https://localhost:4200"", 21 | ""http://localhost:4200"", 22 | ""https://localhost:9002"", 23 | ""https://.*\\.model-t\\.cc\\.commerce\\.ondemand\\.com"" 24 | ]" -------------------------------------------------------------------------------- /docker-resources/configure-db.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Wait $TIMEOUT seconds for SQL Server to start up by ensuring that 4 | # calling SQLCMD does not return an error code, which will ensure that sqlcmd is accessible 5 | # and that system and user databases return "0" which means all databases are in an "online" state 6 | # https://docs.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-databases-transact-sql?view=sql-server-2017 7 | 8 | DBSTATUS=1 9 | ERRCODE=1 10 | i=0 11 | TIMEOUT=120 12 | 13 | while [[ "${DBSTATUS:-1}" -ne "0" ]] && [[ "$i" -lt "$TIMEOUT" ]]; do 14 | i=$((i+1)) 15 | DBSTATUS_STR="$(/opt/mssql-tools/bin/sqlcmd -h -1 -t 1 -S "$SQLSERVER" -U sa -P "$SA_PASSWORD" -Q "SET NOCOUNT ON; Select SUM(state) from sys.databases")" 16 | DBSTATUS=${DBSTATUS_STR//[ $'\001'-$'\037']} 17 | ERRCODE=$? 18 | sleep 1 19 | done 20 | if [ "$DBSTATUS" -ne "0" ] || [ "$ERRCODE" -ne 0 ]; then 21 | echo "SQL Server took more than $TIMEOUT seconds to start up or one or more databases are not in an ONLINE state" 22 | exit 1 23 | fi 24 | echo "SQL Server is up; Starting initialization..." 25 | # Run the setup script to create the DB and the schema in the DB 26 | /opt/mssql-tools/bin/sqlcmd -S "$SQLSERVER" -U sa -P "$SA_PASSWORD" -d master -i db_init.sql 27 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/resources/modelt-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 15 | 16 | 17 | 18 | 19 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /core-customize/manifest-to-properties.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Extract properties from manifest.json to convert them to *.properties files 4 | 5 | # REQUIRES: jq - https://stedolan.github.io/jq/ 6 | 7 | MANIFEST_FILE=${1:-manifest.json} 8 | 9 | # Manifest Spec 10 | # https://help.sap.com/viewer/1be46286b36a4aa48205be5a96240672/SHIP/en-US/3d562b85b37a460a92d32ec991459133.html 11 | 12 | PERSONAS=( 13 | 'null' 14 | '"development"' 15 | '"production"' 16 | '"staging"' 17 | ) 18 | ASPECTS=( 19 | '"accstorefront"' 20 | '"admin"' 21 | '"api"' 22 | '"backgroundProcessing"' 23 | '"backoffice"' 24 | ) 25 | 26 | # top-level properties 27 | echo '' 28 | for i in "${PERSONAS[@]}" 29 | do 30 | echo "-------------Persona: $i-------------" 31 | echo '' 32 | jq --raw-output \ 33 | ".properties[] | select(.persona == $i) | .key + \"=\" + .value" \ 34 | "$MANIFEST_FILE" \ 35 | | sort | uniq 36 | echo '' 37 | done 38 | 39 | # aspect-specific properties 40 | for i in "${ASPECTS[@]}" 41 | do 42 | for j in "${PERSONAS[@]}" 43 | do 44 | echo "-------------Aspect: $i | Persona: $j-------------" 45 | echo '' 46 | jq --raw-output \ 47 | ".aspects[] | select(.name == $i) | 48 | .properties[]? | select(.persona == $j) | .key + \"=\" + .value" \ 49 | "$MANIFEST_FILE" \ 50 | | sort | uniq 51 | echo '' 52 | done 53 | done -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/web/src/de/hybris/platform/modelt/controller/ModeltReadinessController.java: -------------------------------------------------------------------------------- 1 | package de.hybris.platform.modelt.controller; 2 | 3 | import de.hybris.platform.modelt.readinesscheck.ReadinessCheckResult; 4 | import de.hybris.platform.modelt.readinesscheck.ReadinessCheckService; 5 | import de.hybris.platform.modelt.readinesscheck.ReadinessStatus; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.beans.factory.annotation.Qualifier; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RequestMethod; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | @RestController 14 | public class ModeltReadinessController { 15 | 16 | @Autowired 17 | @Qualifier("readinessCheckService") 18 | private ReadinessCheckService readinessCheckService; 19 | 20 | @RequestMapping(value = "/status", method = RequestMethod.GET) 21 | public ResponseEntity isReady() { 22 | ReadinessCheckResult readinessCheckResult = readinessCheckService.checkReadiness(); 23 | if (ReadinessStatus.READY == readinessCheckResult.getReadinessStatus()) { 24 | return ResponseEntity.ok("ready"); 25 | } 26 | return ResponseEntity.status(readinessCheckResult.getHttpStatus()).body("not ready yet"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/src/de/hybris/platform/modelt/readinesscheck/impl/DefaultReadinessCheckService.java: -------------------------------------------------------------------------------- 1 | package de.hybris.platform.modelt.readinesscheck.impl; 2 | 3 | import de.hybris.platform.modelt.readinesscheck.ReadinessCheck; 4 | import de.hybris.platform.modelt.readinesscheck.ReadinessCheckResult; 5 | import de.hybris.platform.modelt.readinesscheck.ReadinessCheckService; 6 | import de.hybris.platform.modelt.readinesscheck.ReadinessStatus; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.beans.factory.annotation.Required; 10 | import org.springframework.util.CollectionUtils; 11 | 12 | import java.util.List; 13 | 14 | public class DefaultReadinessCheckService implements ReadinessCheckService { 15 | 16 | private List readinessChecks; 17 | 18 | @Override 19 | public ReadinessCheckResult checkReadiness() { 20 | if (CollectionUtils.isEmpty(readinessChecks)) { 21 | return ReadinessCheckResult.ready(); 22 | } 23 | 24 | for (ReadinessCheck readinessCheck : readinessChecks) { 25 | if (ReadinessStatus.READY != readinessCheck.getResult().getReadinessStatus()) { 26 | return readinessCheck.getResult(); 27 | } 28 | } 29 | 30 | return ReadinessCheckResult.ready(); 31 | } 32 | 33 | @Required 34 | public void setReadinessChecks(final List readinessChecks) { 35 | this.readinessChecks = readinessChecks; 36 | } 37 | } -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/src/de/hybris/platform/modelt/readinesscheck/ReadinessCheckResult.java: -------------------------------------------------------------------------------- 1 | package de.hybris.platform.modelt.readinesscheck; 2 | 3 | import org.springframework.http.HttpStatus; 4 | 5 | public class ReadinessCheckResult { 6 | private final ReadinessStatus readinessStatus; 7 | private final HttpStatus httpStatus; 8 | private final String message; 9 | 10 | public ReadinessCheckResult(final ReadinessStatus readinessStatus, final HttpStatus httpStatus, 11 | final String message) { 12 | this.readinessStatus = readinessStatus; 13 | this.httpStatus = httpStatus; 14 | this.message = message; 15 | } 16 | 17 | public ReadinessStatus getReadinessStatus() { 18 | return readinessStatus; 19 | } 20 | 21 | public HttpStatus getHttpStatus() { 22 | return httpStatus; 23 | } 24 | 25 | public String getMessage() { 26 | return message; 27 | } 28 | 29 | public static ReadinessCheckResult ready() { 30 | return new ReadinessCheckResult(ReadinessStatus.READY, HttpStatus.OK, null); 31 | } 32 | 33 | public static ReadinessCheckResult notReady() { 34 | return new ReadinessCheckResult(ReadinessStatus.NOT_READY, HttpStatus.SERVICE_UNAVAILABLE, null); 35 | } 36 | 37 | public static ReadinessCheckResult error(final String message) { 38 | return new ReadinessCheckResult(ReadinessStatus.ERROR, HttpStatus.INTERNAL_SERVER_ERROR, message); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /core-customize/.gitignore: -------------------------------------------------------------------------------- 1 | # Folders to ignore, whatever the place they are 2 | .DS_Store 3 | .metadata 4 | classes 5 | testclasses 6 | eclipsebin 7 | gensrc 8 | 9 | # Folders to ignore at the root of the repository 10 | hybris/roles/ 11 | hybris/log/ 12 | hybris/temp/ 13 | hybris/data/ 14 | hybris/config/local-config/99-local.properties 15 | 16 | # only allow custom extension 17 | hybris/bin/* 18 | !hybris/bin/custom/ 19 | 20 | #IDE files 21 | .gradle 22 | .idea 23 | idea-module-files 24 | *.iml 25 | com.springsource.sts.config.flow.prefs 26 | org.sonar.ide.eclipse.core.prefs 27 | HybrisCodeGeneration.launch 28 | 29 | org.springframework.ide.eclipse.beans.core.prefs 30 | org.springframework.ide.eclipse.core.prefs 31 | .springBeans 32 | 33 | # Filename patterns to ignore 34 | lib/.lastupdate 35 | *.class 36 | build.xml 37 | Generated*.java 38 | platformhome.properties 39 | *testclasses.xml 40 | extensioninfo.xsd 41 | *hmc.jar 42 | hmc.xsd 43 | items.xsd 44 | beans.xsd 45 | ruleset.xml 46 | *.log 47 | .pmd 48 | *build.number 49 | 50 | base.properties 51 | # Addon specific copy folders 52 | **/_ui/addons 53 | **/views/addons 54 | **/tld/addons 55 | **/tags/addons 56 | **/messages/addons 57 | **/lib/addons 58 | **/web/addonsrc 59 | **/_ui-src/addons 60 | **/web/addontestsrc 61 | **/web/commonwebsrc/*/ 62 | **/web/webroot/WEB-INF/lib/addon-* 63 | wro_addons.xml 64 | 65 | # Backoffice artifacts 66 | *_bof.jar 67 | 68 | # project ignore 69 | /build/ 70 | /dependencies/ 71 | /cloud-extension-pack/ 72 | gradle.properties 73 | hybris/config/local.properties 74 | hybris/config/solr/instances/default/configsets 75 | 76 | # developer-specific properties 77 | hybris/config/local-config/99-local.properties -------------------------------------------------------------------------------- /js-storefront/README.md: -------------------------------------------------------------------------------- 1 | # JS Storefront Template 2 | 3 | ## Requirements 4 | 5 | See [Recommended Development Environment][requirements]. 6 | 7 | - [Angular CLI](https://angular.io/): **17.0** or later. 8 | - node.js: 20.9.0 or later 9 | - yarn 10 | 11 | [requirements]: https://help.sap.com/docs/SAP_COMMERCE_COMPOSABLE_STOREFRONT/cfcf687ce2544bba9799aa6c8314ecd0/bf31098d779f4bdebb7a2d0591917363.html?locale=en-US 12 | 13 | ## Getting started 14 | 15 | To bootstrap a new Spartacus storefront: 16 | 17 | 1. Get credentials at the [Repository based shipment channel][rbsc] 18 | 2. Export your base64 NPM credentials as Environment variable `RBSC_NPM_CREDENTIALS`. 19 | 3. Run the bootstrap script with your repo name 20 | ```bash 21 | ./boostrap.sh 22 | ``` 23 | 4. You can delete the `bootstrap` folder and script afterwards. 24 | 25 | [rbsc]: https://ui.repositories.cloud.sap/www/webapp/users/ 26 | 27 | ## What does the script do? 28 | 29 | - Bootstraps a new Spartacus project from scratch as recommended by the official documentation (with PWA and SSR support) 30 | - Generate a `manifest.json` for CCv2 with correct settings for [Client Side][csr] and [Server Side Rendering][ssr] 31 | - Generate a `.npmrc` for configuration as described in [Installing Composable Storefront Libraries from the Repository 32 | Based Shipment Channel][library] with a variable placeholder. 33 | 34 | [library]: https://help.sap.com/docs/SAP_COMMERCE_COMPOSABLE_STOREFRONT/cfcf687ce2544bba9799aa6c8314ecd0/5de67850bd8d487181fef9c9ba59a31d.html?locale=en-US#installing-composable%0Astorefront-libraries-from-the-repository-based-shipment-channel 35 | [build]: https://help.sap.com/viewer/b2f400d4c0414461a4bb7e115dccd779/LATEST/en-US/63577f67a67347bf9f4765a5385ead33.html 36 | [issue]: https://github.com/SAP/spartacus/issues/5886 37 | 38 | [ssr]: https://help.sap.com/viewer/b2f400d4c0414461a4bb7e115dccd779/LATEST/en-US/cd5b94c25a68456ba5840f942f33f68b.html 39 | [csr]: https://help.sap.com/viewer/b2f400d4c0414461a4bb7e115dccd779/LATEST/en-US/0d54fc7faaa44b14b15b164cb1f3f2b6.html 40 | -------------------------------------------------------------------------------- /core-customize/bootstrap/config-template/localextensions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/web/webroot/WEB-INF/config/modelt-web-app-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | 11 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 52 | 53 | -------------------------------------------------------------------------------- /core-customize/gradle.properties: -------------------------------------------------------------------------------- 1 | # SAP Commerce Suite 2011 2 | com.sap.softwaredownloads.commerceSuite.2011.14.downloadUrl=https://softwaredownloads.sap.com/file/0020000001791292021 3 | com.sap.softwaredownloads.commerceSuite.2011.14.checksum=8df31cd2e78b016fa983e14aca0e2b78b91e1fab02ed7cf44d5a5ac84665a2d5 4 | com.sap.softwaredownloads.commerceSuite.2011.15.downloadUrl=https://softwaredownloads.sap.com/file/0020000001825962021 5 | com.sap.softwaredownloads.commerceSuite.2011.15.checksum=fa2100113f44743e2071e33af34d64178e1733a291d66e7d5af111c00a1aa898 6 | 7 | # SAP Commerce Suite 2105 8 | com.sap.softwaredownloads.commerceSuite.2105.4.downloadUrl=https://softwaredownloads.sap.com/file/0020000001791262021 9 | com.sap.softwaredownloads.commerceSuite.2105.4.checksum=9cc16b492d56c96ee58b5be7c4ab6d67d421431da54e593baed470e751a01bfe 10 | com.sap.softwaredownloads.commerceSuite.2105.5.downloadUrl=https://softwaredownloads.sap.com/file/0020000001825982021 11 | com.sap.softwaredownloads.commerceSuite.2105.5.checksum=7cd560a42f165966873694e2e3c80779aac2902561b6034978deab33b5481a60 12 | 13 | # SAP Commerce Integrations 2005 14 | com.sap.softwaredownloads.commerceIntegrations.2005.4.downloadUrl=https://softwaredownloads.sap.com/file/0020000001002682021 15 | com.sap.softwaredownloads.commerceIntegrations.2005.4.checksum=afe8b7be15eb3d96e44f70e802a22aa34e979c78ab09a38121592ef9144ac079 16 | com.sap.softwaredownloads.commerceIntegrations.2005.5.downloadUrl=https://softwaredownloads.sap.com/file/0020000001165032021 17 | com.sap.softwaredownloads.commerceIntegrations.2005.5.checksum=b367a36084e63540e39ffbcfd7dbc037e0dd6685bfefc68e0ed60064fcca3de0 18 | 19 | # SAP Commerce Integrations 2102 20 | com.sap.softwaredownloads.commerceIntegrations.2102.3.downloadUrl=https://softwaredownloads.sap.com/file/0020000001395712021 21 | com.sap.softwaredownloads.commerceIntegrations.2102.3.checksum=1930e7177c49aec2ada3826b5db5094d90d17f85fb8535b668b2274964e3b16b 22 | com.sap.softwaredownloads.commerceIntegrations.2102.4.downloadUrl=https://softwaredownloads.sap.com/file/0020000001508662021 23 | com.sap.softwaredownloads.commerceIntegrations.2102.4.checksum=0334de7dcc0917cdded35db05623f688205a0012ef96e6bd316a28cf55bb5af6 24 | 25 | # SAP Commerce Integrations 2108 26 | com.sap.softwaredownloads.commerceIntegrations.2108.1.downloadUrl=https://softwaredownloads.sap.com/file/0020000001508642021 27 | com.sap.softwaredownloads.commerceIntegrations.2108.1.checksum=200f8c9f59bd14f9ab247af9e3efb5ecd2061ac070ab3b9019f31c7a2f20f000 28 | com.sap.softwaredownloads.commerceIntegrations.2108.2.downloadUrl=https://softwaredownloads.sap.com/file/0020000001645522021 29 | com.sap.softwaredownloads.commerceIntegrations.2108.2.checksum=be97def776bcae60ed31de91d1421da0ae8ec02eca6945467af9eabe3f6c470a 30 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/web/webroot/WEB-INF/config/modelt-spring-mvc-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 47 | 48 | /WEB-INF/messages 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /core-customize/bootstrap-extras.gradle.kts: -------------------------------------------------------------------------------- 1 | import java.net.http.* 2 | import java.time.Duration 3 | import java.net.URI 4 | import groovy.json.JsonSlurper 5 | import de.undercouch.gradle.tasks.download.Download 6 | 7 | buildscript { 8 | repositories { 9 | mavenCentral() 10 | maven { 11 | url = uri("https://plugins.gradle.org/m2/") 12 | } 13 | } 14 | dependencies { 15 | classpath("de.undercouch:gradle-download-task:5.5.0") 16 | } 17 | } 18 | 19 | val EXTRAS_SOURCE = "build/extras" 20 | val EXTRAS_TARGET = "hybris/bin/custom/extras" 21 | val extraExtensions = mapOf( 22 | "sanecleanup" to "https://api.github.com/repos/sap-commerce-tools/sanecleanup/releases/latest", 23 | "environment-ribbon" to "https://api.github.com/repos/sap-commerce-tools/environment-ribbon/releases/latest", 24 | "hacvcsinfo" to "https://api.github.com/repos/sap-commerce-tools/hacvcsinfo/releases/latest" 25 | ) 26 | val allExtras = tasks.register("bootstrapExtras") { 27 | description = "Download and unpack extras extension" 28 | group = "Bootstrap" 29 | } 30 | 31 | val client = HttpClient.newBuilder() 32 | .followRedirects(HttpClient.Redirect.NORMAL) 33 | .connectTimeout(Duration.ofSeconds(30)) 34 | .build() 35 | extraExtensions.forEach { 36 | val url = tasks.register("extras_getLatest_${it.key}") { 37 | doLast { 38 | val request = HttpRequest.newBuilder(URI(it.value)) 39 | .GET() 40 | .build() 41 | val response = client.send(request, HttpResponse.BodyHandlers.ofString()) 42 | val body = response.body() 43 | val parsed = JsonSlurper().parseText(body) as Map 44 | extra.set("zipball", parsed["zipball_url"]) 45 | } 46 | } 47 | val down = tasks.register("extras_download_${it.key}") { 48 | dependsOn(url) 49 | 50 | src(provider({url.get().extra.get("zipball")})) 51 | dest(file("${EXTRAS_SOURCE}/${it.key}.zip")) 52 | overwrite(true) 53 | tempAndMove(true) 54 | onlyIfModified(true) 55 | useETag(true) 56 | } 57 | 58 | val bootstrap = tasks.register("extras_bootstrap_${it.key}") { 59 | dependsOn(down) 60 | doLast { 61 | ant.withGroovyBuilder { 62 | "delete"("includeEmptyDirs" to true) { 63 | "fileset"("dir" to "${EXTRAS_TARGET}/${it.key}", "defaultexcludes" to false, "erroronmissingdir" to false) 64 | } 65 | } 66 | copy { 67 | from(zipTree("${EXTRAS_SOURCE}/${it.key}.zip")) 68 | into(EXTRAS_TARGET) 69 | eachFile { 70 | val newPath = relativePath.segments.drop(1).toMutableList() 71 | newPath.add(0, it.key) 72 | relativePath = RelativePath(true, *newPath.toTypedArray()) 73 | } 74 | includeEmptyDirs = false 75 | } 76 | } 77 | } 78 | allExtras.configure{ 79 | dependsOn(bootstrap) 80 | } 81 | } -------------------------------------------------------------------------------- /core-customize/bootstrap/demo/manifest.jsonnet.patch: -------------------------------------------------------------------------------- 1 | --- manifest.jsonnet 2021-04-25 07:07:10.000000000 +0200 2 | +++ manifest.jsonnet 2021-04-25 07:07:58.000000000 +0200 3 | @@ -30,8 +30,39 @@ 4 | local storefrontContextRoot = ''; 5 | local storefrontAddons = [ 6 | 'smarteditaddon', 7 | - //TODO: add more addons as required here 8 | - // don't forget to add them to localextensions.xml too! 9 | + 10 | + 'adaptivesearchsamplesaddon', 11 | + 'assistedservicecustomerinterestsaddon', 12 | + 'assistedservicepromotionaddon', 13 | + 'assistedservicestorefront', 14 | + 'assistedserviceyprofileaddon', 15 | + 'captchaaddon', 16 | + 'configurablebundleaddon', 17 | + 'consignmenttrackingaddon', 18 | + 'customercouponaddon', 19 | + 'customercouponsamplesaddon', 20 | + 'customerinterestsaddon', 21 | + 'customerticketingaddon', 22 | + 'eventtrackingwsaddon', 23 | + 'merchandisingaddon', 24 | + 'merchandisingstorefrontsampledataaddon', 25 | + 'multicountrysampledataaddon', 26 | + 'notificationaddon', 27 | + 'ordermanagementaddon', 28 | + 'orderselfserviceaddon', 29 | + 'pcmbackofficesamplesaddon', 30 | + 'personalizationaddon', 31 | + 'personalizationsampledataaddon', 32 | + 'personalizationyprofilesampledataaddon', 33 | + 'profiletagaddon', 34 | + 'selectivecartsplitlistaddon', 35 | + 'stocknotificationaddon', 36 | + 'textfieldconfiguratortemplateaddon', 37 | + 'timedaccesspromotionengineaddon', 38 | + 'timedaccesspromotionenginesamplesaddon', 39 | + 'xyformssamples', 40 | + 'xyformsstorefrontcommons', 41 | + 'ysapproductconfigaddon', 42 | ]; 43 | 44 | local smartEditWebapps = [ 45 | @@ -46,19 +77,18 @@ 46 | webapp('cmswebservices'), 47 | webapp('permissionswebservices'), 48 | webapp('previewwebservices'), 49 | - //TODO: add/remove smartedit features here 50 | - // don't forget to add the extensions to localextensions.xml too! 51 | - // // Smartedit personalization 52 | - // webapp('personalizationsmartedit'), 53 | - // webapp('personalizationwebservices'), 54 | - // // Smartedit personalization promotion 55 | - // webapp('personalizationpromotionssmartedit'), 56 | - // // Smartedit personalization search 57 | - // webapp('personalizationsearchsmartedit'), 58 | - // // Smartedit promotion 59 | - // webapp('merchandisingcmswebservices'), 60 | - // // https://help.sap.com/viewer/50c996852b32456c96d3161a95544cdb/1905/en-US/b21fa18f635d49eaa4d9ce5997a6a814.html 61 | - // webapp('merchandisingsmartedit'), 62 | + 63 | + // Smartedit personalization 64 | + webapp('personalizationsmartedit'), 65 | + webapp('personalizationwebservices'), 66 | + // Smartedit personalization promotion 67 | + webapp('personalizationpromotionssmartedit'), 68 | + // Smartedit personalization search 69 | + webapp('personalizationsearchsmartedit'), 70 | + // Smartedit promotion 71 | + webapp('merchandisingcmswebservices'), 72 | + // https://help.sap.com/viewer/50c996852b32456c96d3161a95544cdb/1905/en-US/b21fa18f635d49eaa4d9ce5997a6a814.html 73 | + webapp('merchandisingsmartedit'), 74 | ]; 75 | 76 | // ------------ MANIFEST ------------ 77 | @@ -139,6 +169,9 @@ 78 | webapps: [ 79 | webapp(storefrontExtension, storefrontContextRoot), 80 | webapp('mediaweb'), 81 | + 82 | + webapp('orbeonweb'), 83 | + webapp('xyformsweb'), 84 | ], 85 | }, 86 | { 87 | -------------------------------------------------------------------------------- /core-customize/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 1>&2 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 50 | echo. 1>&2 51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 52 | echo location of your Java installation. 1>&2 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 1>&2 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 64 | echo. 1>&2 65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 66 | echo location of your Java installation. 1>&2 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 74 | 75 | 76 | @rem Execute Gradle 77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 78 | 79 | :end 80 | @rem End local scope for the variables with windows NT shell 81 | if %ERRORLEVEL% equ 0 goto mainEnd 82 | 83 | :fail 84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 85 | rem the _cmd.exe /c_ return code! 86 | set EXIT_CODE=%ERRORLEVEL% 87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 89 | exit /b %EXIT_CODE% 90 | 91 | :mainEnd 92 | if "%OS%"=="Windows_NT" endlocal 93 | 94 | :omega 95 | -------------------------------------------------------------------------------- /js-storefront/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -e 3 | 4 | RED=$(tput setaf 1) 5 | GREEN=$(tput setaf 2) 6 | YELLOW=$(tput setaf 3) 7 | BRIGHT=$(tput bold) 8 | NORMAL=$(tput sgr0) 9 | 10 | progress() { 11 | printf "%b%b--- %s ---%b\n" "$GREEN" "$BRIGHT" "$1" "$NORMAL" 12 | } 13 | warning() { 14 | printf "%b%s%b\n" "$YELLOW" "$1" "$NORMAL" 15 | } 16 | error() { 17 | printf "%b%s%b\n" "$RED" "$1" "$NORMAL" 18 | } 19 | 20 | NAME=$1 21 | 22 | if [ -z "$NAME" ]; then 23 | echo "Usage: ./bootstrap.sh " 24 | exit 1 25 | fi 26 | 27 | # https://sap.github.io/spartacus-docs/building-the-spartacus-storefront-from-libraries-4-x/ 28 | # yarn global add @angular/cli@latest 29 | 30 | if ! command -v 'yarn' > /dev/null 2>&1 31 | then 32 | error "yarn not found" 33 | error "please install it to continue" 34 | error "https://classic.yarnpkg.com/en/docs/install" 35 | exit 1 36 | fi 37 | 38 | if ! command -v 'ng' > /dev/null 2>&1 39 | then 40 | error "Angular CLI (ng) not found" 41 | error "please install @angular/cli@17" 42 | error "> yarn global add @angular/cli@17" 43 | exit 1 44 | fi 45 | 46 | NG_VERSION="$(ng version | grep '@angular-devkit/core' | awk '{ print $2 }')" 47 | if case $NG_VERSION in 17.*) false;; *) true;; esac; then 48 | error "Wrong angular version, please use Angular 17 (@angular/cli@latest)" 49 | exit 1 50 | fi 51 | 52 | progress "Bootstrapping Angular project '$NAME'" 53 | ng new "$NAME" \ 54 | --skip-install \ 55 | --skip-git \ 56 | --style=scss \ 57 | --standalone=false \ 58 | --routing=false \ 59 | --package-manager=yarn 60 | ( 61 | cd "$NAME" || exit 1 62 | 63 | cat > .npmrc <<-EOF 64 | @spartacus:registry=https://73554900100900004337.npmsrv.base.repositories.cloud.sap/ 65 | //73554900100900004337.npmsrv.base.repositories.cloud.sap/:_auth=\${RBSC_NPM_CREDENTIALS} 66 | always-auth=true 67 | EOF 68 | 69 | progress "Adding Spartacus (PWA and SSR enabled)" 70 | echo "> Recommended minimal features: Cart, Product, SmartEdit" 71 | echo "> Just confirm the empty defaults for SmartEdit preview route and allow origin" 72 | ng add @spartacus/schematics@2211.23 \ 73 | --pwa \ 74 | --ssr \ 75 | --use-meta-tags 76 | progress "Applying optimizations" 77 | cp -r "../bootstrap/.vscode" . 78 | angular="$(grep -i '@angular/animations' package.json | awk '{ print $2 }')" 79 | yarn install 80 | ) 81 | progress "Generating Manifest" 82 | if [ -f "manifest.json" ]; then 83 | backup="manifest.$(date +%F_%H%M%S).json" 84 | warning "manifest.json found; backing up to $backup" 85 | mv -f "manifest.json" "$backup" 86 | fi 87 | cat > manifest.json <<-EOF 88 | { 89 | "applications": [ 90 | { 91 | "name": "$NAME", 92 | "path": "$NAME", 93 | "ssr": { 94 | "enabled": true, 95 | "path": "dist/$NAME/server/main.js" 96 | }, 97 | "csr": { 98 | "webroot": "dist/$NAME/browser/" 99 | }, 100 | "enabledRepositories": [ 101 | "spartacus-6" 102 | ] 103 | } 104 | ], 105 | "nodeVersion": "20" 106 | } 107 | EOF 108 | progress "FINISHED" 109 | echo "Next steps:" 110 | echo "- Update the baseSite.context with the correct baseSite, currency etc." 111 | echo " https://sap.github.io/spartacus-docs/building-the-spartacus-storefront-from-libraries-4-x/#checking-spartacus-configurationmodulets-for-base-url-and-other-settings" 112 | echo "- Update smartedit whitelisting in spartacus-configuration.module.ts" 113 | echo " https://sap.github.io/spartacus-docs/smartEdit-setup-instructions-for-spartacus/" 114 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/web/webroot/WEB-INF/config/modelt-spring-security-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | CustomerGroup 73 | 74 | 75 | 76 | 77 | Customer 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /core-customize/bootstrap/config-template/cloud/local-dev.properties: -------------------------------------------------------------------------------- 1 | # local-dev.properties 2 | 3 | #*****************************************************************************# 4 | # Local Database 5 | 6 | db.url=jdbc:sqlserver://localhost:1433;databaseName=localdev;responseBuffering=adaptive;loginTimeout=10;disableStatementPooling=false;statementPoolingCacheSize=1000 7 | db.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver 8 | db.username=localdev 9 | db.password=localdev1! 10 | db.tableprefix= 11 | 12 | #*****************************************************************************# 13 | # Sane Defaults 14 | 15 | installed.tenants=junit 16 | initialpassword.admin=nimda 17 | 18 | tomcat.mem=-Xms4G -Xmx4G 19 | 20 | #ref. hybris/bin/platform/project.properties 21 | tomcat.generaloptions=${tomcat.jdkmodules.config} \ 22 | -Djava.locale.providers=COMPAT,CLDR \ 23 | ${tomcat.mem} \ 24 | -XX:+UseStringDeduplication \ 25 | -ea \ 26 | -Dcatalina.base=%CATALINA_BASE% \ 27 | -Dcatalina.home=%CATALINA_HOME% \ 28 | -Dfile.encoding=UTF-8 \ 29 | -Djava.util.logging.config.file=jdk_logging.properties \ 30 | -Djava.io.tmpdir="${HYBRIS_TEMP_DIR}" 31 | 32 | #ref. hybris/bin/platform/resources/advanced.properties 33 | standalone.javaoptions=${tomcat.mem} -Djava.locale.providers=COMPAT,CLDR 34 | 35 | ribbon.environment.code=local 36 | ribbon.environment.type=development 37 | 38 | # faster startup / update system etc 39 | backoffice.fill.typefacade.cache.on.startup=false 40 | backoffice.solr.search.index.autoinit=false 41 | 42 | # disable audit for faster init/update 43 | auditing.enabled=false 44 | 45 | # supress spurious update-backofficeIndex-CronJob message if index not available 46 | log4j2.logger.indexer.name=de.hybris.platform.solrfacetsearch.indexer.strategies.impl.AbstractIndexerStrategy 47 | log4j2.logger.indexer.level=WARN 48 | 49 | system.unlocking.disabled=false 50 | 51 | # don't start cronjobs automatically 52 | cronjob.timertask.loadonstartup=false 53 | 54 | #*****************************************************************************# 55 | # Endpoints for local development 56 | 57 | ccv2.services.api.url.0=https://localhost:${tomcat.ssl.port} 58 | ccv2.services.accstorefront.url.0=https://@projectName@site.test:${tomcat.ssl.port} 59 | ccv2.services.backoffice.url.0=https://localhost:${tomcat.ssl.port} 60 | ccv2.services.jsapps.url.0=https://localhost:4200 61 | 62 | corsfilter.commercewebservices.allowedOrigins=${ccv2.services.accstorefront.url.0} ${ccv2.services.jsapps.url.0} http://localhost:4200 63 | 64 | @projectName@storefront.webroot= 65 | hac.webroot=/hac 66 | 67 | #*****************************************************************************# 68 | # Local Cloud Hotfolder 69 | 70 | cluster.node.groups=integration,yHotfolderCandidate,backgroundProcessing 71 | azure.hotfolder.storage.account.connection-string=UseDevelopmentStorage=true 72 | azure.hotfolder.storage.account.name=devstoreaccount1 73 | cloud.hotfolder.default.images.root.url=http://127.0.0.1:10000/${azure.hotfolder.storage.account.name}/${azure.hotfolder.storage.container.name}/${tenantId}/images 74 | cloud.hotfolder.default.images.media.folder.qualifier=azureimages 75 | 76 | #*****************************************************************************# 77 | # Local Solr Cloud 78 | 79 | solrserver.instances.default.autostart=false 80 | solrserver.instances.cloud.autostart=true 81 | 82 | # Force the Default configuration to use cloud mode + default zookeeper endpoint 83 | solr.config.Default.mode=CLOUD 84 | solr.config.Default.urls=localhost:9983 85 | 86 | #*****************************************************************************# 87 | # Development Mode 88 | 89 | addonfilter.active=true 90 | ansi.colors=true 91 | build.development.mode=true 92 | development.mode=true 93 | tomcat.development.mode=true 94 | 95 | # Backoffice Dev Settings 96 | # https://help.sap.com/viewer/5c9ea0c629214e42b727bf08800d8dfa/latest/en-US/8b48115b86691014991ad2131153834f.html 97 | backoffice.cockpitng.development.mode=true 98 | # disable all caching for development 99 | backoffice.cockpitng.additionalResourceLoader.enabled=true 100 | backoffice.cockpitng.uifactory.cache.enabled=false 101 | backoffice.cockpitng.widgetclassloader.resourcecache.enabled=false 102 | backoffice.cockpitng.resourceloader.resourcecache.enabled=false 103 | cockpitng.widgetclassloader.resourcecache.enabled=false 104 | 105 | backoffice.sass.source.map.enabled=true 106 | 107 | # backoffice hot deployment 108 | backoffice.cockpitng.hotDeployment.enabled=true 109 | 110 | #reset backoffice config every login 111 | # https://help.sap.com/viewer/5c9ea0c629214e42b727bf08800d8dfa/latest/en-US/8b7db2c286691014af65a6a21e6d5933.html 112 | # backoffice.cockpitng.reset.triggers=login 113 | # backoffice.cockpitng.reset.scope=widgets,cockpitConfig 114 | -------------------------------------------------------------------------------- /core-customize/bootstrap/config-template/cloud/common.properties: -------------------------------------------------------------------------------- 1 | # cloud/common.properties 2 | 3 | #*****************************************************************************# 4 | # Sane Defaults 5 | 6 | sqlserver.enableLimitSupportForSQLServer2012=true 7 | 8 | # TODO: adapt this to your requirements 9 | lang.packs=en 10 | 11 | # Suppress spurious logs 12 | log4j2.logger.nosolr.name=de.hybris.platform.solrfacetsearch.indexer.cron.SolrIndexerJob 13 | log4j2.logger.nosolr.level=WARN 14 | log4j2.logger.nglogin.name=com.hybris.cockpitng.composer.LoginFormComposer 15 | log4j2.logger.nglogin.level=WARN 16 | log4j2.logger.cleanup.name=de.hybris.platform.retention.job.AfterRetentionCleanupJobPerformable 17 | log4j2.logger.cleanup.level=WARN 18 | log4j2.logger.cleanuplogs.name=de.hybris.platform.jobs.maintenance.impl.CleanUpLogsStrategy 19 | log4j2.logger.cleanuplogs.level=WARN 20 | 21 | 22 | # TODO: adapt this your project requirements 23 | # Disable audit, decrease session timeout 24 | # https://help.sap.com/viewer/1be46286b36a4aa48205be5a96240672/SHIP/en-US/d6794b766aea4783b829988dc587f978.html 25 | auditing.enabled=false 26 | default.session.timeout=360 27 | 28 | addonfilter.active=false 29 | 30 | csrf.allowed.url.patterns=/[^/]+(/[^?]*)+(sop/response)$,/[^/]+(/[^?]*)+(merchant_callback)$,/[^/]+(/[^?]*)+(hop/response)$,/[^/]+(/[^?]*)+(language)$,/[^/]+(/[^?]*)+(currency)$,/(events)$ 31 | occ.rewrite.overlapping.paths.enabled=true 32 | 33 | # junit tenant is only necessary if you execute tests in the Commerce Cloud build pipeline 34 | # (i.e. when you configure `tests` / `webTests` in `manifest.json`) 35 | installed.tenants= 36 | 37 | # disable system update during runtime 38 | system.unlocking.disabled=true 39 | 40 | # prevent tasks / cronjobs from starting until server is fully up 41 | # -> faster startup 42 | task.polling.startup.delay.enabled=true 43 | 44 | #*****************************************************************************# 45 | # B2C 46 | 47 | # TODO: align with the contextPath of the storefront in the manifest! 48 | # don't forget to update local-dev.properties accordingly 49 | storefrontContextRoot= 50 | 51 | # website.@projectName@site.http=${ccv2.services.accstorefront.url.0} 52 | 53 | #*****************************************************************************# 54 | # Spartacus B2C 55 | 56 | # website.@projectName@site-spa.http=${ccv2.services.jsapps.url.0} 57 | # website.@projectName@site-spa.https=${ccv2.services.jsapps.url.0} 58 | 59 | # ref. commercewebservices/project.properties 60 | webroot.commercewebservices.http=${ccv2.services.api.url.0}/occ 61 | webroot.commercewebservices.https=${ccv2.services.api.url.0}/occ 62 | commercewebservices.oauth2.tokenUrl=${ccv2.services.api.url.0}/authorizationserver/oauth/token 63 | 64 | # Whitelisting SmartEdit for your Storefront 65 | # https://help.sap.com/viewer/9d346683b0084da2938be8a285c0c27a/LATEST/en-US/fb742b29cf3c4e81aac7c131c0441172.html 66 | smarteditaddon.javascript.paths.responsive=/shared/common/js/webApplicationInjector.js?allow-origin=localhost:9002,*.*.model-t.cc.commerce.ondemand.com:443;/shared/common/js/reprocessPage.js;/shared/common/js/adjustComponentRenderingToSE.js;/responsive/common/js/smarteditaddon.js 67 | 68 | # https://sap.github.io/spartacus-docs/cors/ 69 | # TODO: review the allowedOrigins with your security team! 70 | corsfilter.commercewebservices.allowedOrigins=${ccv2.services.accstorefront.url.0} ${ccv2.services.jsapps.url.0} 71 | corsfilter.commercewebservices.allowedMethods=GET HEAD OPTIONS PATCH PUT POST DELETE 72 | corsfilter.commercewebservices.allowedHeaders=origin content-type accept authorization cache-control x-anonymous-consents x-profile-tag-debug x-consent-reference occ-personalization-id occ-personalization-time 73 | corsfilter.commercewebservices.exposedHeaders=x-anonymous-consents occ-personalization-id occ-personalization-time 74 | corsfilter.commercewebservices.allowCredentials=true 75 | 76 | corsfilter.assistedservicewebservices.allowedOrigins=${ccv2.services.accstorefront.url.0} ${ccv2.services.jsapps.url.0} 77 | corsfilter.assistedservicewebservices.allowedMethods=GET HEAD OPTIONS PATCH PUT POST DELETE 78 | corsfilter.assistedservicewebservices.allowedHeaders=origin content-type accept authorization cache-control x-anonymous-consents x-profile-tag-debug x-consent-reference occ-personalization-id occ-personalization-time 79 | corsfilter.assistedservicewebservices.exposedHeaders=x-anonymous-consents occ-personalization-id occ-personalization-time 80 | corsfilter.assistedservicewebservices.allowCredentials=true 81 | 82 | corsfilter.personalizationwebservices.allowedOrigins=${ccv2.services.accstorefront.url.0} ${ccv2.services.jsapps.url.0} 83 | corsfilter.permissionswebservices.allowedOrigins=${ccv2.services.accstorefront.url.0} ${ccv2.services.jsapps.url.0} 84 | 85 | #*****************************************************************************# 86 | # Update System Configuration 87 | 88 | # TODO: for more fine-grained control, use "Configuring Commerce Update Parameters" 89 | # https://help.sap.com/viewer/0fa6bcf4736c46f78c248512391eb467/SHIP/en-US/75132dba6afc47dba8ba59dbd899e075.html 90 | 91 | # Configuration for Update process type which is used for ant updatesystem script - default value is true 92 | # update.updateRunningSystem.enabled=true 93 | # update.clearHmcConfiguration.enabled=true 94 | # update.importEssentialData.enabled=true 95 | # update.localizeTypes.enabled=true 96 | update.rebuildLucenesearchIndexes.enabled=false 97 | # Import project data of these extensions (comma-separated list) 98 | # update.executeProjectData.extensionName.list= 99 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/web/webroot/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 10 | 11 | modelt 12 | 13 | 14 | BASIC 15 | 16 | 17 | 18 | 19 | 20 | 500 21 | /500.jsp 22 | 23 | 24 | 25 | 404 26 | /404.jsp 27 | 28 | 29 | 30 | 405 31 | /405.jsp 32 | 33 | 34 | 35 | 403 36 | /login.jsp?login_error=1 37 | 38 | 39 | 40 | 401 41 | /login.jsp?login_error=1 42 | 43 | 44 | 45 | XSSFilter 46 | de.hybris.platform.servicelayer.web.XSSFilter 47 | 48 | 49 | 50 | characterEncodingFilter 51 | org.springframework.web.filter.CharacterEncodingFilter 52 | 53 | encoding 54 | UTF-8 55 | 56 | 57 | forceEncoding 58 | true 59 | 60 | 61 | 62 | 63 | modeltPlatformFilterChain 64 | org.springframework.web.filter.DelegatingFilterProxy 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | XSSFilter 76 | /* 77 | 78 | 79 | 80 | characterEncodingFilter 81 | /* 82 | 83 | 84 | 85 | modeltPlatformFilterChain 86 | /* 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 104 | 105 | contextConfigLocation 106 | WEB-INF/config/modelt-web-app-config.xml 107 | 108 | 109 | 110 | de.hybris.platform.spring.HybrisContextLoaderListener 111 | 112 | 113 | 114 | org.springframework.web.context.request.RequestContextListener 115 | 116 | 117 | 118 | springmvc 119 | org.springframework.web.servlet.DispatcherServlet 120 | 121 | contextConfigLocation 122 | WEB-INF/config/modelt-spring-mvc-config.xml 123 | 124 | 1 125 | 126 | 127 | 128 | springmvc 129 | / 130 | 131 | 132 | 133 | 120 134 | COOKIE 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /core-customize/bootstrap-demo.gradle.kts: -------------------------------------------------------------------------------- 1 | import mpern.sap.commerce.build.tasks.HybrisAntTask 2 | import com.github.difflib.UnifiedDiffUtils 3 | import com.github.difflib.DiffUtils 4 | 5 | plugins { 6 | id("sap.commerce.build") version("4.0.0") 7 | id("sap.commerce.build.ccv2") version("4.0.0") 8 | id("de.undercouch.download") version("5.5.0") 9 | } 10 | 11 | buildscript { 12 | repositories { 13 | mavenCentral() 14 | } 15 | dependencies { 16 | classpath("com.databricks:sjsonnet_2.13:0.4.0") 17 | classpath("io.github.java-diff-utils:java-diff-utils:4.10") 18 | } 19 | } 20 | 21 | val bootstrapDemo = tasks.register("bootstrapDemo") { 22 | group = "Boostrap" 23 | description = "Bootstrap demo project based on 'cx' recipe" 24 | } 25 | 26 | defaultTasks("bootstrapDemo") 27 | 28 | tasks.register("bootstrapDefaultProject") { 29 | buildFile = file("bootstrap.gradle.kts") 30 | startParameter.projectProperties = mapOf( 31 | "projectName" to "demoshop", 32 | "rootPackage" to "com.demo.shop" 33 | ) 34 | } 35 | bootstrapDemo.configure { 36 | dependsOn("bootstrapDefaultProject") 37 | } 38 | tasks.register("fixcmsflexcomponent") { 39 | dependsOn("bootstrapDefaultProject") 40 | doLast { 41 | ant.withGroovyBuilder { 42 | "touch"("file" to "hybris/bin/custom/demoshop/demoshopstorefront/web/webroot/WEB-INF/views/responsive/cms/cmsflexcomponent.jsp") 43 | } 44 | } 45 | } 46 | tasks.register("downloadSpartacusSampleData") { 47 | src("https://github.com/SAP-samples/cloud-commerce-sample-setup/releases/download/sampledata/spartacussampledata-version-2211-x.zip") 48 | dest("dependencies") 49 | onlyIfModified(true) 50 | useETag(true) 51 | } 52 | 53 | tasks.register("unpackSpartacus") { 54 | dependsOn("downloadSpartacusSampleData", "bootstrapDefaultProject") 55 | from(zipTree("dependencies/spartacussampledata.2211.zip")) 56 | into("hybris/bin/custom/spartacussampledata") 57 | // eachFile { 58 | // val newPath = relativePath.segments.drop(1).toMutableList() 59 | // newPath.add(0, "spartacussampledata") 60 | // relativePath = RelativePath(true, *newPath.toTypedArray()) 61 | // } 62 | includeEmptyDirs = false 63 | } 64 | // ant extgen -Dinput.template=yacceleratorordermanagement -Dinput.name=demoshopordermanagement -Dinput.package=com.demo.shop.ordermanagement 65 | tasks.register("generateDemoOrderManagment") { 66 | dependsOn("bootstrapDefaultProject") 67 | 68 | args("extgen") 69 | antProperty("input.template", "yacceleratorordermanagement") 70 | antProperty("input.name", "demoshopordermanagement") 71 | antProperty("input.package", "com.demo.shop.ordermanagement") 72 | } 73 | tasks.register("extraExtensions") { 74 | dependsOn("unpackSpartacus", "generateDemoOrderManagment", "fixcmsflexcomponent") 75 | } 76 | 77 | val extrasFolder = file("bootstrap/demo/config-extras") 78 | val configFolder = file("hybris/config") 79 | 80 | tasks.register("copyExtraConfig") { 81 | dependsOn("extraExtensions") 82 | from(extrasFolder) { 83 | exclude("**/*.properties") 84 | } 85 | into(configFolder) 86 | duplicatesStrategy = DuplicatesStrategy.INCLUDE 87 | } 88 | 89 | val patchProps = tasks.register("patchProperties") 90 | 91 | extrasFolder 92 | .walk() 93 | .filter{it.isFile() && it.extension.equals("properties")} 94 | .forEach{ 95 | val relative = it.relativeTo(extrasFolder) 96 | val target = configFolder.resolve(relative) 97 | val patch = tasks.register("patchProperties_${relative.toString().replace("[/\\\\]".toRegex(), "-")}") { 98 | dependsOn("extraExtensions") 99 | doLast { 100 | var newContent = "" 101 | if (target.exists()) { 102 | newContent = target.readText() 103 | newContent += "\n" 104 | } 105 | newContent += it.readText() 106 | target.writeText(newContent) 107 | } 108 | } 109 | patchProps.configure{ 110 | dependsOn(patch) 111 | } 112 | } 113 | 114 | val manifestJsonnet = file("manifest.jsonnet") 115 | tasks.register("patchManifestJsonnet") { 116 | mustRunAfter("bootstrapDefaultProject") 117 | doLast { 118 | val original = manifestJsonnet.readLines() 119 | val diff = file("bootstrap/demo/manifest.jsonnet.patch").readLines() 120 | 121 | val patch = UnifiedDiffUtils.parseUnifiedDiff(diff); 122 | val result = DiffUtils.patch(original, patch); 123 | 124 | manifestJsonnet.writeText(result.joinToString("\n")) 125 | } 126 | } 127 | tasks.register("regenerateManifest") { 128 | dependsOn("patchManifestJsonnet") 129 | doLast { 130 | sjsonnet.SjsonnetMain.main0( 131 | arrayOf("--output-file", "manifest.json", "manifest.jsonnet"), 132 | sjsonnet.SjsonnetMain.createParseCache(), 133 | java.lang.System.`in`, 134 | java.lang.System.`out`, 135 | java.lang.System.err, 136 | os.Path(project.rootDir.toPath()), 137 | scala.`None$`.empty(), 138 | scala.`None$`.empty() 139 | ) 140 | } 141 | } 142 | tasks.register("updateConfiguration") { 143 | dependsOn("copyExtraConfig", "patchProperties", "regenerateManifest") 144 | } 145 | 146 | bootstrapDemo.configure { 147 | dependsOn("updateConfiguration") 148 | doLast { 149 | println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") 150 | println("!!! To finish the setup please run !!!") 151 | println("!!! ./gradlew setupLocalDevelopment !!!") 152 | println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /core-customize/bootstrap/manifest.jsonnet: -------------------------------------------------------------------------------- 1 | // find . -name 'extensioninfo.xml' | \ 2 | // xargs xml sel -t -v '//extension/@name' -o ": '" -v '//webmodule/@webroot' -o "'," -n | \ 3 | // grep -v "^\(.\+\): '/\1',$" | grep '/' 4 | 5 | local nonstandard_context_paths = { 6 | mediaweb: '/medias', 7 | testweb: '/test', 8 | oauth2: '/authorizationserver', 9 | maintenanceweb: '/maintenance', 10 | commercewebservices: '/occ', 11 | ycommercewebservices: '/rest', 12 | scimwebservices: '/scim', 13 | orbeonweb: '/web-orbeon', 14 | }; 15 | 16 | local webapp(extension, path=null) = { 17 | name: extension, 18 | contextPath: if path == null then 19 | if extension in nonstandard_context_paths then 20 | nonstandard_context_paths[extension] 21 | else 22 | '/' + extension 23 | else 24 | path, 25 | }; 26 | 27 | // CONFIGURE YOUR MANIFEST HERE 28 | 29 | local storefrontContextRoot = ''; 30 | local storefrontAddons = [ 31 | 'smarteditaddon', 32 | //TODO: add more addons as required here 33 | // don't forget to add them to localextensions.xml too! 34 | ]; 35 | 36 | local smartEditWebapps = [ 37 | // Activating SmartEdit for a Storefront 38 | // https://help.sap.com/viewer/1be46286b36a4aa48205be5a96240672/SHIP/en-US/7d3f83250d9846518f4154cfb18ae051.html 39 | // Default Smartedit webapps 40 | webapp('oauth2'), 41 | webapp('smartedit'), 42 | webapp('cmssmartedit'), 43 | webapp('cmssmarteditwebservices'), 44 | webapp('smarteditwebservices'), 45 | webapp('cmswebservices'), 46 | webapp('permissionswebservices'), 47 | webapp('previewwebservices'), 48 | //TODO: add/remove smartedit features here 49 | // don't forget to add the extensions to localextensions.xml too! 50 | // // Smartedit personalization 51 | // webapp('personalizationsmartedit'), 52 | // webapp('personalizationwebservices'), 53 | // // Smartedit personalization promotion 54 | // webapp('personalizationpromotionssmartedit'), 55 | // // Smartedit personalization search 56 | // webapp('personalizationsearchsmartedit'), 57 | // // Smartedit promotion 58 | // webapp('merchandisingcmswebservices'), 59 | // // https://help.sap.com/viewer/50c996852b32456c96d3161a95544cdb/1905/en-US/b21fa18f635d49eaa4d9ce5997a6a814.html 60 | // webapp('merchandisingsmartedit'), 61 | ]; 62 | 63 | // ------------ MANIFEST ------------ 64 | function(intExtPackVersion=null, solrVersion=null, solrCustom='solr', accStorefrontEnabled=false, storefrontExtension=nulll, commerceVersion='2211.23') { 65 | commerceSuiteVersion: commerceVersion, 66 | extensionPacks: [ 67 | ] + if intExtPackVersion != null then [ 68 | { 69 | name: 'hybris-commerce-integrations', 70 | version: intExtPackVersion, 71 | }, 72 | ] else [], 73 | extensions: [ 74 | // modeltacceleratorservices is only available in CCv2 (not part of the cloud extension pack) 75 | // -> configure it in manifest.json 76 | // https://help.sap.com/viewer/0fa6bcf4736c46f78c248512391eb467/SHIP/en-US/b13c673497674994a7f243e3225af9b3.html 77 | 'modeltacceleratorservices', 78 | ], 79 | useConfig: { 80 | properties: [ 81 | { 82 | location: 'hybris/config/cloud/common.properties', 83 | }, 84 | { 85 | location: 'hybris/config/cloud/aspect/api.properties', 86 | aspect: 'api', 87 | }, 88 | { 89 | location: 'hybris/config/cloud/aspect/backoffice.properties', 90 | aspect: 'backoffice', 91 | }, 92 | { 93 | location: 'hybris/config/cloud/aspect/backgroundprocessing.properties', 94 | aspect: 'backgroundProcessing', 95 | }, 96 | { 97 | location: 'hybris/config/cloud/aspect/admin.properties', 98 | aspect: 'admin', 99 | }, 100 | { 101 | location: 'hybris/config/cloud/persona/development.properties', 102 | persona: 'development', 103 | }, 104 | ] + if accStorefrontEnabled then [ 105 | { 106 | location: 'hybris/config/cloud/aspect/accstorefront.properties', 107 | aspect: 'accstorefront', 108 | }, 109 | ] else [], 110 | extensions: { 111 | location: 'hybris/config/localextensions.xml', 112 | exclude: [], 113 | }, 114 | } + if solrVersion != null && solrCustom != null then { 115 | solr: { 116 | location: solrCustom, 117 | }, 118 | } 119 | else {}, 120 | properties: [], 121 | storefrontAddons: [] + if accStorefrontEnabled then [ 122 | { addon: addon, storefront: storefrontExtension, template: 'yacceleratorstorefront' } 123 | for addon in storefrontAddons 124 | ] else [], 125 | aspects: [ 126 | { 127 | name: 'backoffice', 128 | webapps: [ 129 | webapp('hac'), 130 | webapp('mediaweb'), 131 | webapp('backoffice'), 132 | webapp('odata2webservices'), 133 | ] + smartEditWebapps, 134 | }, 135 | { 136 | name: 'backgroundProcessing', 137 | properties: [], 138 | webapps: [ 139 | webapp('hac'), 140 | webapp('mediaweb'), 141 | ], 142 | }, 143 | { 144 | name: 'api', 145 | properties: [], 146 | webapps: [ 147 | webapp('commercewebservices'), 148 | // only necessary for checkout/payment mocks 149 | // https://help.sap.com/viewer/4c33bf189ab9409e84e589295c36d96e/latest/en-US/8abddeed86691014be559318fab13d44.html 150 | webapp('acceleratorservices'), 151 | webapp('oauth2'), 152 | webapp('mediaweb'), 153 | ], 154 | }, 155 | ] + if accStorefrontEnabled then [ 156 | { 157 | name: 'accstorefront', 158 | properties: [], 159 | webapps: [ 160 | webapp(storefrontExtension, storefrontContextRoot), 161 | webapp('mediaweb'), 162 | ], 163 | }, 164 | ] else [], 165 | } + if solrVersion != null then { 166 | // https://help.sap.com/viewer/1be46286b36a4aa48205be5a96240672/latest/en-US/b35bc14a62aa4950bdba451a5f40fc61.html#loiod7294323e5e542b7b37f48dd83565321 167 | solrVersion: solrVersion, 168 | } else {} 169 | -------------------------------------------------------------------------------- /core-customize/README.md: -------------------------------------------------------------------------------- 1 | # SAP Commerce Project Template for CCv2 2 | 3 | > **Initial project bootstrap** 4 | > 5 | > 1. Download the latest SAP Commerce 2211 release zip file and put it into the `dependencies` folder 6 | > using the correct file name, e.g. 7 | > 8 | > ```bash 9 | > cp ~/Downloads/CXCOMCL221100U_23*.ZIP ./dependencies/hybris-commerce-suite-2211.23.zip 10 | > ``` 11 | > *Or* configure your S-User (e.g. using `gradle.properties`) and run `./gradlew downloadAndVerifyPlatform` 12 | > 2. Repeat the same for Integration extension pack if you want to use it. 13 | > 3. Download the [cloudhotfolders ZIP] into the `dependencies` folder (save as `cloudhotfolders-2211.zip`). If you 14 | > don't need cloudhotfolders locally you can also remove them from the `build.gradle.kts` and the generated 15 | > `localextensions.xml` after the next step. 16 | > 4. Bootstrap the starting point for your Commerce project by running the following command: 17 | > 18 | > ```bash 19 | > ./gradlew -b bootstrap.gradle.kts \ 20 | > -PprojectName= \ 21 | > -ProotPackage= 22 | > ``` 23 | > **Read the output!** 24 | > 25 | > The following optional settings are available: 26 | > - `-PintExtPackVersion=2102.1` enable "SAP Commerce Cloud, Integration Extension Pack" with version. 27 | > - `-PsolrVersion=9.2` set the solr version for the manifest. To check which versions are supported, see 28 | > Third-Party compatibility of the [Update Release Notes][update] of your selected version. 29 | > - `-PaccStorefrontEnabled` enable code generation for the deprecated accelerator storefront. 30 | > 31 | > 5. Review the generated configuration in `hybris/config`, especially the `hybris/config/environment/*.properties` 32 | > files and `localextensions.xml` (search for `TODO:` comments) 33 | > 6. Update the `manifest.jsonnet` (again, search for `TODO:` comments).\ 34 | > You can use the [jsonnet] file to update the `manifest.json` for your project. 35 | > 7. Delete all bootstrap files, you don't need them any more: 36 | > 37 | > ```bash 38 | > rm -r bootstrap* 39 | > ``` 40 | > 41 | > 8. Delete this quote and the demo-section at the bottom of this README 42 | > 9. Commit and push the changes to your project repository :) 43 | 44 | [update]: https://help.sap.com/docs/SAP_COMMERCE_CLOUD_PUBLIC_CLOUD/75d4c3895cb346008545900bffe851ce/f18f6a711d07462b80137df6ed533eee.html?locale=en-US&q=Compatibility%20Matrix 45 | [cloudhotfolders ZIP]: https://me.sap.com/notes/2817992 46 | 47 | We use Gradle + [commerce-gradle-plugin][plugin] to automate whole project setup. 48 | 49 | [plugin]: https://github.com/SAP/commerce-gradle-plugin 50 | 51 | ## Setup local development 52 | 53 | ```sh 54 | git clone 55 | cd 56 | docker-compose up -d 57 | cd core-customize 58 | ./gradlew setupLocalDevelopment 59 | ./gradlew yclean yall 60 | ./gradlew yinitialize 61 | ``` 62 | 63 | ## FAQ 64 | 65 | ### How to use manifest.jsonnet? 66 | 67 | To generate the `manifest.json` with [Jsonnet][jsonnet]: 68 | 69 | ```bash 70 | jsonnet --output-file manifest.json manifest.jsonnet 71 | ``` 72 | 73 | [jsonnet]: https://jsonnet.org/ 74 | 75 | ### How do I add an addon to my storefront? 76 | 77 | 1. Add the addon to the `manifest.json` (either by hand or via `manifest.jsonnet`, [documentation][addon]) 78 | 2. Run `./gradlew installManifestAddon` 79 | 3. Reformat `/extensioninfo.xml` (unfortunately, the the platform build messes it up when adding addons) 80 | 4. Commit/push your changes 81 | 5. Tell your team to run `./gradlew installManifestAddon` after pulling your changes. 82 | 83 | [addon]: https://help.sap.com/viewer/1be46286b36a4aa48205be5a96240672/LATEST/en-US/9a3ab7d08c704fccb7fd899e876d41d6.html 84 | 85 | ## Why does the configuration work for local development and the cloud? 86 | 87 | By combining the [configuration reuse][reuse] mechanism of CCv2, the [optional configuration folder][folder] 88 | of Commerce and a bit of clever symlinking of files and folders, we can use the same configuration 89 | locally and in the cloud. 90 | 91 | This setup uses: 92 | 93 | - `hybris/config/localextensions.xml` to configure extensions 94 | - `hybris/config/cloud/**/*.properties` to configure properties per CCv2 aspect and/or persona. 95 | There is one file per aspect, plus the special file `local-dev.properties` that configures the local development environment. 96 | - `hybris/config/local-config` is configured as `hybris.optional.config.dir` and contains *symlinks* 97 | to the relevant property files in `hybris/config/cloud` (by default: `common.properties`, `persona/development.properties` and `local-dev.properties`).\ 98 | **Important** `local.properties` must not be modified at all (that's why it is in `.gitignore`). 99 | - If you have any configuration specific to your local machine, put it in `hybris/config/local-config/99-local.properties`. 100 | - If the local setup changes for the whole project, update `hybris/config/cloud/local-dev.properties` 101 | - If you enabled solr customization during bootstrap (`./gradle -b boostrap.gradle.kts enableSolrCustomization`), the default cloud solr configuration set is moved to the correct folder structure for CCv2 ([documentation][solr]). 102 | A symlink in `hybris/config/solr` allows you to use the same configuration locally. 103 | 104 | ``` 105 | core-customize 106 | ├── ... 107 | ├── hybris 108 | ├── ... 109 | │ ├── config 110 | │ │ ├── cloud 111 | +--------------------> accstorefront.properties 112 | +--------------------> admin.properties 113 | +--------------------> api.properties 114 | +--------------------> backgroundprocessing.properties 115 | +--------------------> backoffice.properties 116 | +--------------------> common.properties <---+ 117 | | │ │ │ └── local-dev.properties <--+ | 118 | | │ │ ├── ... | | symlinks 119 | | │ │ ├── local-config | | 120 | manifest.json | │ │ │ ├── 10-local.properties +-----+ 121 | useConfig | │ │ │ ├── 50-local.properties +---+ 122 | properties | │ │ │ └── 99-local.properties 123 | ... +-------------+ │ │ ├── local.properties 124 | extensions +--------------------------> localextensions.xml 125 | solr +---------+ │ │ ├── readme.txt 126 | | │ │ ├── solr 127 | | │ │ │ └── instances 128 | | │ │ │ └── cloud 129 | | │ │ │ ├── configsets +-------+ 130 | | │ │ │ ├── ... | 131 | | │ │ │ └── zoo.cfg | 132 | | │ │ └── ... | 133 | | ├── ... | symlink 134 | +----------------> solr | 135 | │ └── server | 136 | │ └── solr | 137 | │ └── configsets <-------------+ 138 | │ └── default 139 | │ └── conf 140 | │ ├── lang 141 | │ ├── protwords.txt 142 | │ ├── schema.xml 143 | │ ├── solrconfig.xml 144 | │ ├── stopwords.txt 145 | │ └── synonyms.txt 146 | └── ... 147 | 148 | ``` 149 | 150 | [reuse]: https://help.sap.com/viewer/1be46286b36a4aa48205be5a96240672/LATEST/en-US/2311d89eef9344fc81ef168ac9668307.html 151 | [folder]: https://help.sap.com/viewer/b490bb4e85bc42a7aa09d513d0bcb18e/LATEST/en-US/8beb75da86691014a0229cf991cb67e4.html 152 | [solr]: https://help.sap.com/viewer/b2f400d4c0414461a4bb7e115dccd779/LATEST/en-US/f7251d5a1d6848489b1ce7ba46300fe6.html 153 | 154 | ## Demo Setup 155 | 156 | The file `bootstrap-demo.gradle.kts` bootstraps a demo storefront based on the `cx` [recipe][recipe], 157 | including the `spartacussampledata` extension (necessary to demo the Spartacus storefront; [documentation][spartacussample]) 158 | 159 | To generate the demo, run: 160 | ``` 161 | ./gradlew -b bootstrap-demo.gradle.kts 162 | ``` 163 | [spartacussample]: https://sap.github.io/spartacus-docs/spartacussampledata-extension/ 164 | [recipe]: https://help.sap.com/viewer/a74589c3a81a4a95bf51d87258c0ab15/2011/en-US/f09d46cf4a2546b586ed7021655e4715.html 165 | -------------------------------------------------------------------------------- /core-customize/gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | ############################################################################## 22 | # 23 | # Gradle start up script for POSIX generated by Gradle. 24 | # 25 | # Important for running: 26 | # 27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 28 | # noncompliant, but you have some other compliant shell such as ksh or 29 | # bash, then to run this script, type that shell name before the whole 30 | # command line, like: 31 | # 32 | # ksh Gradle 33 | # 34 | # Busybox and similar reduced shells will NOT work, because this script 35 | # requires all of these POSIX shell features: 36 | # * functions; 37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 39 | # * compound commands having a testable exit status, especially «case»; 40 | # * various built-in commands including «command», «set», and «ulimit». 41 | # 42 | # Important for patching: 43 | # 44 | # (2) This script targets any POSIX shell, so it avoids extensions provided 45 | # by Bash, Ksh, etc; in particular arrays are avoided. 46 | # 47 | # The "traditional" practice of packing multiple parameters into a 48 | # space-separated string is a well documented source of bugs and security 49 | # problems, so this is (mostly) avoided, by progressively accumulating 50 | # options in "$@", and eventually passing that to Java. 51 | # 52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 54 | # see the in-line comments for details. 55 | # 56 | # There are tweaks for specific operating systems such as AIX, CygWin, 57 | # Darwin, MinGW, and NonStop. 58 | # 59 | # (3) This script is generated from the Groovy template 60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 61 | # within the Gradle project. 62 | # 63 | # You can find Gradle at https://github.com/gradle/gradle/. 64 | # 65 | ############################################################################## 66 | 67 | # Attempt to set APP_HOME 68 | 69 | # Resolve links: $0 may be a link 70 | app_path=$0 71 | 72 | # Need this for daisy-chained symlinks. 73 | while 74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 75 | [ -h "$app_path" ] 76 | do 77 | ls=$( ls -ld "$app_path" ) 78 | link=${ls#*' -> '} 79 | case $link in #( 80 | /*) app_path=$link ;; #( 81 | *) app_path=$APP_HOME$link ;; 82 | esac 83 | done 84 | 85 | # This is normally unused 86 | # shellcheck disable=SC2034 87 | APP_BASE_NAME=${0##*/} 88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s 90 | ' "$PWD" ) || exit 91 | 92 | # Use the maximum available, or set MAX_FD != -1 to use that value. 93 | MAX_FD=maximum 94 | 95 | warn () { 96 | echo "$*" 97 | } >&2 98 | 99 | die () { 100 | echo 101 | echo "$*" 102 | echo 103 | exit 1 104 | } >&2 105 | 106 | # OS specific support (must be 'true' or 'false'). 107 | cygwin=false 108 | msys=false 109 | darwin=false 110 | nonstop=false 111 | case "$( uname )" in #( 112 | CYGWIN* ) cygwin=true ;; #( 113 | Darwin* ) darwin=true ;; #( 114 | MSYS* | MINGW* ) msys=true ;; #( 115 | NONSTOP* ) nonstop=true ;; 116 | esac 117 | 118 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 119 | 120 | 121 | # Determine the Java command to use to start the JVM. 122 | if [ -n "$JAVA_HOME" ] ; then 123 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 124 | # IBM's JDK on AIX uses strange locations for the executables 125 | JAVACMD=$JAVA_HOME/jre/sh/java 126 | else 127 | JAVACMD=$JAVA_HOME/bin/java 128 | fi 129 | if [ ! -x "$JAVACMD" ] ; then 130 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 131 | 132 | Please set the JAVA_HOME variable in your environment to match the 133 | location of your Java installation." 134 | fi 135 | else 136 | JAVACMD=java 137 | if ! command -v java >/dev/null 2>&1 138 | then 139 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 140 | 141 | Please set the JAVA_HOME variable in your environment to match the 142 | location of your Java installation." 143 | fi 144 | fi 145 | 146 | # Increase the maximum file descriptors if we can. 147 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 148 | case $MAX_FD in #( 149 | max*) 150 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 151 | # shellcheck disable=SC2039,SC3045 152 | MAX_FD=$( ulimit -H -n ) || 153 | warn "Could not query maximum file descriptor limit" 154 | esac 155 | case $MAX_FD in #( 156 | '' | soft) :;; #( 157 | *) 158 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 159 | # shellcheck disable=SC2039,SC3045 160 | ulimit -n "$MAX_FD" || 161 | warn "Could not set maximum file descriptor limit to $MAX_FD" 162 | esac 163 | fi 164 | 165 | # Collect all arguments for the java command, stacking in reverse order: 166 | # * args from the command line 167 | # * the main class name 168 | # * -classpath 169 | # * -D...appname settings 170 | # * --module-path (only if needed) 171 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 172 | 173 | # For Cygwin or MSYS, switch paths to Windows format before running java 174 | if "$cygwin" || "$msys" ; then 175 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 176 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 177 | 178 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 179 | 180 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 181 | for arg do 182 | if 183 | case $arg in #( 184 | -*) false ;; # don't mess with options #( 185 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 186 | [ -e "$t" ] ;; #( 187 | *) false ;; 188 | esac 189 | then 190 | arg=$( cygpath --path --ignore --mixed "$arg" ) 191 | fi 192 | # Roll the args list around exactly as many times as the number of 193 | # args, so each arg winds up back in the position where it started, but 194 | # possibly modified. 195 | # 196 | # NB: a `for` loop captures its iteration list before it begins, so 197 | # changing the positional parameters here affects neither the number of 198 | # iterations, nor the values presented in `arg`. 199 | shift # remove old arg 200 | set -- "$@" "$arg" # push replacement arg 201 | done 202 | fi 203 | 204 | 205 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 206 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 207 | 208 | # Collect all arguments for the java command: 209 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, 210 | # and any embedded shellness will be escaped. 211 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be 212 | # treated as '${Hostname}' itself on the command line. 213 | 214 | set -- \ 215 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 216 | -classpath "$CLASSPATH" \ 217 | org.gradle.wrapper.GradleWrapperMain \ 218 | "$@" 219 | 220 | # Stop when "xargs" is not available. 221 | if ! command -v xargs >/dev/null 2>&1 222 | then 223 | die "xargs is not available" 224 | fi 225 | 226 | # Use "xargs" to parse quoted args. 227 | # 228 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 229 | # 230 | # In Bash we could simply go: 231 | # 232 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 233 | # set -- "${ARGS[@]}" "$@" 234 | # 235 | # but POSIX shell has neither arrays nor command substitution, so instead we 236 | # post-process each arg (as a line of input to sed) to backslash-escape any 237 | # character that might be a shell metacharacter, then use eval to reverse 238 | # that process (while maintaining the separation between arguments), and wrap 239 | # the whole thing up as a single "set" statement. 240 | # 241 | # This will of course break if any of these variables contains a newline or 242 | # an unmatched quote. 243 | # 244 | 245 | eval "set -- $( 246 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 247 | xargs -n1 | 248 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 249 | tr '\n' ' ' 250 | )" '"$@"' 251 | 252 | exec "$JAVACMD" "$@" 253 | -------------------------------------------------------------------------------- /core-customize/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.apache.tools.ant.taskdefs.condition.Os 2 | 3 | import de.undercouch.gradle.tasks.download.Download 4 | import de.undercouch.gradle.tasks.download.Verify 5 | 6 | import java.time.Instant 7 | 8 | plugins { 9 | id("sap.commerce.build") version("4.0.0") 10 | id("sap.commerce.build.ccv2") version("4.0.0") 11 | id("de.undercouch.download") version("5.5.0") // for downloading solr-9.x.tgz and optionally SAP Commerce Cloud zips. 12 | `maven-publish` // for publishing to the local maven repo 13 | } 14 | 15 | val solrVersionMap = mapOf( // 16 | /* 17 | * version 8 unfortunately has a different download URL and is currently not working. But it is the version that is 18 | * supplied with the standard zip, so we're fine unless the solr version is changed and then changed back in 19 | * manifest.json 20 | */ 21 | "8.11" to "8.11.2", // 22 | "9.2" to "9.2.1", // 23 | "9.5" to "9.5.0" 24 | ) 25 | val solrVersion = solrVersionMap[CCV2.manifest.solrVersion] ?: "9.2.1" 26 | 27 | val cloudHotfolderVersion = "2211" 28 | 29 | val dependencyDir = "dependencies" 30 | val workingDir = project.projectDir 31 | val binDir = "${workingDir}/hybris/bin" 32 | 33 | repositories { 34 | flatDir { dirs(dependencyDir) } 35 | mavenCentral() 36 | } 37 | 38 | val cloudHotfolderExtensions: Configuration by configurations.creating 39 | val solrServer: Configuration by configurations.creating 40 | 41 | dependencies { 42 | cloudHotfolderExtensions("de.hybris.platform:cloudhotfolders:${cloudHotfolderVersion}@zip") 43 | solrServer("org.apache.solr:solr:${solrVersion}") 44 | } 45 | 46 | 47 | hybris { 48 | //Optional mapping of preview version to patch level. 49 | // manifest.json requires the Commerce Suite version in the format 2211.8, while the platform build.number 50 | // uses 2211.FP1. This mapping allows the plugin to convert between the two formats. 51 | previewToPatchLevel = mapOf( 52 | "2211.FP0" to 4, 53 | "2211.FP1" to 8 54 | ) 55 | 56 | // what files should be deleted when cleaning up the platform? 57 | // (cloudhofolders will be downloaded by custom configuration) 58 | cleanGlob.set("glob:**hybris/bin/{modules**,platform**,cloudhotfolders**}") 59 | 60 | // what should be unpacked from the platform zip files? 61 | bootstrapInclude.set( 62 | listOf( 63 | "hybris/**", // 64 | "azurecloudhotfolder/**", // 65 | "cloudcommons/**", // 66 | "cloudhotfolder/**" // 67 | ) 68 | ) 69 | 70 | // what should excluded when unpacking? 71 | // the default value is a npm package folder that includes UTF-8 filenames, which lead to problems on linux 72 | bootstrapExclude.set( 73 | listOf( 74 | "hybris/bin/ext-content/npmancillary/resources/npm/node_modules/http-server/node_modules/ecstatic/test/**" 75 | ) 76 | ) 77 | 78 | //Control the sparse platform bootstrap. 79 | // When enabled, the commerce extensions are extracted from the distribution zip on a as-needed basis. 80 | // Only extensions that are actually used in the project (either directly listed in the localextensions.xml or 81 | // required by other extensions) are extracted. 82 | // The platform itself is always extracted. 83 | // When this mode is enabled, the bootstrapInclude configuration property is ignored. 84 | sparseBootstrap { 85 | // default is disabled 86 | // currently not working in combination with the separate cloudhotfolders zip. 87 | enabled = false 88 | // set of extensions that are always extracted, default is an empty set 89 | alwaysIncluded = listOf() 90 | } 91 | } 92 | 93 | /* 94 | * Cloud hotfolders are transparently provided in commerce cloud. Since some of extensions might depend on them, we 95 | * also have them locally. 96 | */ 97 | tasks.register("bootstrapCloudhotfolder") { 98 | group = "build setup" 99 | dependsOn("bootstrapPlatform") 100 | onlyIf { 101 | !file("${binDir}/cloudhotfolders").exists() 102 | } 103 | 104 | from(zipTree(cloudHotfolderExtensions.singleFile)) 105 | into("${binDir}/cloudhotfolders") 106 | } 107 | 108 | tasks.register("fetchSolr") { 109 | src(uri("https://archive.apache.org/dist/solr/solr/${solrVersion}/solr-${solrVersion}.tgz")) 110 | dest("${dependencyDir}/solr-${solrVersion}.tgz") 111 | overwrite(false) // to only download solr into the dependency folder if it's not there yet. 112 | } 113 | 114 | val repackSolr = tasks.register("repackSolr") { 115 | dependsOn("fetchSolr") 116 | from(tarTree("${dependencyDir}/solr-${solrVersion}.tgz")) 117 | archiveFileName = "solr-${solrVersion}.zip" 118 | destinationDirectory = file(dependencyDir) 119 | } 120 | 121 | publishing { 122 | publications { 123 | create("solr") { 124 | groupId = "org.apache.solr" 125 | artifactId = "solr" 126 | version = solrVersion 127 | 128 | artifact(repackSolr.get().archiveFile) 129 | } 130 | } 131 | } 132 | 133 | tasks.named("yinstallSolr") { 134 | // this task is available because of the solr-publication above. 135 | dependsOn("publishSolrPublicationToMavenLocal") 136 | } 137 | 138 | tasks.ybuild { 139 | dependsOn("publishSolrPublicationToMavenLocal") 140 | group = "build" 141 | } 142 | 143 | tasks.wrapper { 144 | distributionType = Wrapper.DistributionType.ALL 145 | gradleVersion = "8.10.2" 146 | } 147 | 148 | //Optional: automate downloads from launchpad.support.sap.com 149 | // remove this block if you use something better, like Maven 150 | // Recommended reading: 151 | // https://github.com/SAP/commerce-gradle-plugin/blob/master/docs/FAQ.md#downloadPlatform 152 | if (project.hasProperty("sUser") && project.hasProperty("sUserPass")) { 153 | val sUser = project.property("sUser") as String 154 | val sUserPassword = project.property("sUserPass") as String 155 | val authorization = java.util.Base64.getEncoder().encodeToString(("$sUser:$sUserPassword").toByteArray()) 156 | 157 | val commerceVersion = CCV2.manifest.commerceSuiteVersion 158 | val commerceSuiteDownloadUrl = project.property("com.sap.softwaredownloads.commerceSuite.${commerceVersion}.downloadUrl") 159 | val commerceSuiteChecksum = project.property("com.sap.softwaredownloads.commerceSuite.${commerceVersion}.checksum") 160 | 161 | tasks.register("downloadPlatform") { 162 | src(commerceSuiteDownloadUrl) 163 | dest(file("${dependencyDir}/hybris-commerce-suite-${commerceVersion}.zip")) 164 | header("Authorization", "Basic $authorization") 165 | overwrite(false) 166 | tempAndMove(true) 167 | onlyIfModified(true) 168 | useETag(true) 169 | } 170 | 171 | tasks.register("downloadAndVerifyPlatform") { 172 | dependsOn("downloadPlatform") 173 | src(file("${dependencyDir}/hybris-commerce-suite-${commerceVersion}.zip")) 174 | algorithm("SHA-256") 175 | checksum("$commerceSuiteChecksum") 176 | } 177 | 178 | tasks.named("bootstrapPlatform") { 179 | dependsOn("downloadAndVerifyPlatform") 180 | } 181 | 182 | //check if Integration Extension Pack is configured and download it too 183 | if (CCV2.manifest.extensionPacks.any{ "hybris-commerce-integrations" == it.name }) { 184 | val integrationExtensionPackVersion = CCV2.manifest.extensionPacks.first{ "hybris-commerce-integrations" == it.name }.version 185 | val commerceIntegrationsDownloadUrl = project.property("com.sap.softwaredownloads.commerceIntegrations.${integrationExtensionPackVersion}.downloadUrl") 186 | val commerceIntegrationsChecksum = project.property("com.sap.softwaredownloads.commerceIntegrations.${integrationExtensionPackVersion}.checksum") 187 | 188 | tasks.register("downloadIntExtPack") { 189 | src(commerceIntegrationsDownloadUrl) 190 | dest(file("${dependencyDir}/hybris-commerce-integrations-${integrationExtensionPackVersion}.zip")) 191 | header("Authorization", "Basic $authorization") 192 | overwrite(false) 193 | tempAndMove(true) 194 | onlyIfModified(true) 195 | useETag(true) 196 | } 197 | 198 | tasks.register("downloadAndVerifyIntExtPack") { 199 | dependsOn("downloadIntExtPack") 200 | src(file("${dependencyDir}/hybris-commerce-integrations-${integrationExtensionPackVersion}.zip")) 201 | algorithm("SHA-256") 202 | checksum("$commerceIntegrationsChecksum") 203 | } 204 | 205 | tasks.named("bootstrapPlatform") { 206 | dependsOn("downloadAndVerifyIntExtPack") 207 | } 208 | } 209 | } 210 | 211 | tasks.register("generateLocalProperties") { 212 | comment = "GENERATED AT " + Instant.now() 213 | destinationFile = project.file("hybris/config/local.properties") 214 | property("hybris.optional.config.dir", project.file("hybris/config/local-config").absolutePath) 215 | doLast { 216 | mkdir(project.file("hybris/config/local-config/")) 217 | } 218 | } 219 | 220 | val symlinkConfigTask: TaskProvider = tasks.register("symlinkConfig") 221 | val localConfig = file("hybris/config/local-config") 222 | mapOf( 223 | "10-local.properties" to file("hybris/config/cloud/common.properties"), 224 | "20-local.properties" to file("hybris/config/cloud/persona/development.properties"), 225 | "50-local.properties" to file("hybris/config/cloud/local-dev.properties") 226 | ).forEach{ 227 | val symlinkTask = tasks.register("symlink${it.key}") { 228 | val path = it.value.relativeTo(localConfig) 229 | if (Os.isFamily(Os.FAMILY_UNIX)) { 230 | commandLine("sh", "-c", "ln -sfn $path ${it.key}") 231 | } else { 232 | // https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10/ 233 | val windowsPath = path.toString().replace("[/]".toRegex(), "\\") 234 | commandLine("cmd", "/c", """mklink "${it.key}" "$windowsPath" """) 235 | } 236 | workingDir(localConfig) 237 | dependsOn("generateLocalProperties") 238 | } 239 | symlinkConfigTask.configure { 240 | dependsOn(symlinkTask) 241 | } 242 | } 243 | 244 | tasks.register("generateLocalDeveloperProperties") { 245 | dependsOn(symlinkConfigTask) 246 | comment = "my.properties - add your own local development configuration parameters here" 247 | destinationFile = project.file("hybris/config/local-config/99-local.properties") 248 | onlyIf { 249 | !project.file("hybris/config/local-config/99-local.properties").exists() 250 | } 251 | } 252 | 253 | // https://help.sap.com/viewer/b2f400d4c0414461a4bb7e115dccd779/LATEST/en-US/784f9480cf064d3b81af9cad5739fecc.html 254 | tasks.register("enableModeltMock") { 255 | from("hybris/bin/custom/extras/modelt/extensioninfo.disabled") 256 | into("hybris/bin/custom/extras/modelt/") 257 | rename { "extensioninfo.xml" } 258 | } 259 | 260 | tasks.named("installManifestAddons") { 261 | mustRunAfter("generateLocalProperties") 262 | } 263 | 264 | tasks.register("setupLocalDevelopment") { 265 | group = "SAP Commerce" 266 | description = "Setup local development" 267 | dependsOn( 268 | "bootstrapPlatform", 269 | "bootstrapCloudhotfolder", 270 | "yinstallSolr", 271 | "generateLocalDeveloperProperties", 272 | "installManifestAddons", 273 | "enableModeltMock" 274 | ) 275 | } 276 | -------------------------------------------------------------------------------- /core-customize/hybris/bin/custom/extras/modelt/.settings/org.eclipse.jdt.ui.prefs: -------------------------------------------------------------------------------- 1 | comment_clear_blank_lines=true 2 | comment_format_comments=true 3 | comment_format_header=false 4 | comment_format_html=true 5 | comment_format_source_code=true 6 | comment_indent_parameter_description=true 7 | comment_indent_root_tags=true 8 | comment_line_length=160 9 | comment_new_line_for_parameter=false 10 | comment_separate_root_tags=true 11 | eclipse.preferences.version=1 12 | editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true 13 | formatter_settings_version=11 14 | org.eclipse.jdt.ui.exception.name=e 15 | org.eclipse.jdt.ui.gettersetter.use.is=true 16 | org.eclipse.jdt.ui.ignorelowercasenames=true 17 | org.eclipse.jdt.ui.importorder=de.hybris;java;javax;org;com;de; 18 | org.eclipse.jdt.ui.javadoc=true 19 | org.eclipse.jdt.ui.keywordthis=false 20 | org.eclipse.jdt.ui.ondemandthreshold=50 21 | org.eclipse.jdt.ui.overrideannotation=true 22 | org.eclipse.jdt.ui.staticondemandthreshold=50 23 | org.eclipse.jdt.ui.text.custom_code_templates=