diff --git a/.travis.yml b/.travis.yml index ab0c25017f..0c96dade04 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,7 @@ before_script: script: - if [ ${TRAVIS_PULL_REQUEST} != "false" ]; then BUILD_BRANCH=$TRAVIS_PULL_REQUEST_BRANCH; else BUILD_BRANCH=$TRAVIS_BRANCH; fi - ./travis-build.sh -- cd docker && ./builddocker.sh +- cd docker && ./builddocker.sh && ./builddocker-remote-replication.sh - ./pushdocker-travis.sh after_script: diff --git a/admin-base/core/src/main/java/com/peregrine/admin/resource/AdminResourceHandlerService.java b/admin-base/core/src/main/java/com/peregrine/admin/resource/AdminResourceHandlerService.java index b19cd448a8..b3f55f9765 100644 --- a/admin-base/core/src/main/java/com/peregrine/admin/resource/AdminResourceHandlerService.java +++ b/admin-base/core/src/main/java/com/peregrine/admin/resource/AdminResourceHandlerService.java @@ -2018,6 +2018,10 @@ private void updateResourceTree(Resource resource, Map propertie for (Entry entry : properties.entrySet()) { String name = entry.getKey(); + if (!isPropertyCopyable(name)) { + continue; + } + Object value = entry.getValue(); if (value instanceof Map) { applyChildProperties(resource, name, (Map) value); diff --git a/admin-base/core/src/test/java/com/peregrine/admin/resource/TreeTest.java b/admin-base/core/src/test/java/com/peregrine/admin/resource/TreeTest.java deleted file mode 100644 index d7fa9bc7d2..0000000000 --- a/admin-base/core/src/test/java/com/peregrine/admin/resource/TreeTest.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.peregrine.admin.resource; - -import com.peregrine.render.impl.ReferenceListerService.Node; -import com.peregrine.render.impl.ReferenceListerService.Tree; -import com.peregrine.commons.test.AbstractTest; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -public class TreeTest - extends AbstractTest -{ - private static final Logger logger = LoggerFactory.getLogger(TreeTest.class.getName()); - - @Override - public Logger getLogger() { - return logger; - } - - @Test - public void testStringFormat() { - String format = "Test me with: '%s'"; - String value = "ABC"; - String expected = "Test me with: '" + value + "'"; - String actual = String.format(format, "ABC"); - logger.info("String after formatting: '{}'", actual); - assertEquals("String Formatted String is not what is expected", expected, actual); - } - - /** Tests a simple Tree created through creating nodes **/ - @Test - public void testSimpleTreeCreation() { - Tree tree = new Tree(); - Node child = new Node(tree, "a"); - Node grandChild = new Node(child, "b"); - logger.info("Tree 1: '{}'", tree); - assertTrue("Grand Child not found", tree.contains("/a/b")); - - Node grandChild2 = new Node(child, "b2"); - logger.info("Tree 2: '{}'", tree); - assertTrue("Grand Child (2) not found", tree.contains("/a/b2")); - } - - /** Test a Tree using the JCR Resource Path **/ - @Test - public void testTreByPath() { - Tree tree = new Tree().addChildByPath("/a/b/c"); - logger.info("Tree 1: '{}'", tree); - assertTrue("Initial Tree not found", tree.contains("/a/b/c")); - - tree.addChildByPath("/a/b2/c2"); - logger.info("Tree 2: '{}'", tree); - assertTrue("Added 2nd level child not found", tree.contains("/a/b2/c2")); - - tree.addChildByPath("/a2/b/c"); - logger.info("Tree 3: '{}'", tree); - assertTrue("Added 1st level child not found", tree.contains("/a2/b/c")); - - tree.addChildByPath("/a2/b/d/e/f"); - logger.info("Tree 4: '{}'", tree); - assertTrue("Added 3rd level+ child not found", tree.contains("/a2/b/d/e/f")); - } -} \ No newline at end of file diff --git a/admin-base/ui.apps/src/main/content/jcr_root/apps/admin/components/explorerpreviewcontent/template.vue b/admin-base/ui.apps/src/main/content/jcr_root/apps/admin/components/explorerpreviewcontent/template.vue index fe57a1e999..e05da2c5c8 100644 --- a/admin-base/ui.apps/src/main/content/jcr_root/apps/admin/components/explorerpreviewcontent/template.vue +++ b/admin-base/ui.apps/src/main/content/jcr_root/apps/admin/components/explorerpreviewcontent/template.vue @@ -532,15 +532,11 @@ export default { activeTab : function(tab) { if (tab === 'versions'){ this.showVersions() - } else if (tab === 'references'){ - this.showReferencedBy() } }, currentObject : function(path) { - if (this.activeTab === 'versions'){ + if (this.activeTab === 'versions') { this.showVersions() - } else if (this.activeTab === 'references'){ - this.showReferencedBy() } if (this.stateToolsEdit) { this.onEdit() @@ -782,14 +778,6 @@ export default { showVersions() { $perAdminApp.getApi().populateVersions(this.currentObject); }, - showReferencedBy() { - this.loading = true - $perAdminApp.getApi() - .populateReferencedBy(this.currentObject) - .then(() => { - this.loading = false - }) - }, deleteVersion(me, target) { $perAdminApp.stateAction('deleteVersion', { path: target.path, version: target.version.name }); }, diff --git a/docker/Dockerfile b/docker/Dockerfile index a1686c6967..078a367a2a 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,7 +1,5 @@ FROM adoptopenjdk/openjdk11:latest -ENV APP_VERSION 2.0.0 - WORKDIR /app RUN apt update -q \ @@ -15,8 +13,6 @@ RUN apt update -q \ ENV PATH "/usr/local/lib/nodejs/node-v10.16.0-linux-x64/bin:$PATH" -COPY files/* /app/binaries/ -COPY scripts/*.sh /app/scripts/ # Start - Use repository/package pinning to upgrade libvips from version 8.4 to 8.6 COPY overlay/etc/apt/preferences.d/* /etc/apt/preferences.d/ @@ -26,6 +22,8 @@ RUN echo "deb http://archive.ubuntu.com/ubuntu/ focal main restricted" >> /etc/a && apt --only-upgrade install -y libvips libvips-tools # End +COPY files/node-v10.16.0-linux-x64.tar.xz /app/binaries/node-v10.16.0-linux-x64.tar.xz + RUN mkdir -p /usr/local/lib/nodejs \ && tar -xf /app/binaries/node-v10.16.0-linux-x64.tar.xz -C /usr/local/lib/nodejs \ && echo $PATH \ @@ -34,10 +32,17 @@ RUN mkdir -p /usr/local/lib/nodejs \ && echo npx: $(npx -v) \ && apt-get purge -y --auto-remove && rm -rf /var/lib/apt/lists/* && rm -rf /etc/apt/sources.list.d/temp.list; +ARG runmode=none +ENV APP_VERSION 2.0.0 +ENV RUNMODE=${runmode} + +COPY files/* /app/binaries/ +COPY scripts/*.sh /app/scripts/ + RUN scripts/install-sling.sh -RUN scripts/install-peregrine.sh +RUN scripts/install-peregrine.sh ${RUNMODE} -ENTRYPOINT /app/scripts/start.sh && tail -qF /app/sling/logs/error.log +ENTRYPOINT /app/scripts/start.sh ${RUNMODE} && tail -qF /app/sling/logs/error.log #HEALTHCHECK --interval=15s --retries=20 \ # CMD /app/healthcheck.sh diff --git a/docker/README.md b/docker/README.md index ca1ba38a75..3e016aecab 100644 --- a/docker/README.md +++ b/docker/README.md @@ -7,27 +7,38 @@ A prebuilt Peregrine Docker image is available on [Docker Hub](https://hub.docke # Running Peregrine in Docker -1. Pull down the Docker image. +1. Pull down the Docker images. $ docker pull peregrinecms/peregrine-cms:latest + $ docker pull peregrinecms/peregrine-cms:latest-author + $ docker pull peregrinecms/peregrine-cms:latest-publish 2. Run the container. - $ docker run -it -p 8080:8080 peregrinecms/peregrine-cms:latest + $ docker run -it -p 8080:8080 peregrinecms/peregrine-cms:latest -3. Open a browser and visit http://localhost:8080. Login with `admin` / ` admin`. + +3. Open a browser and visit http://localhost:8080 and login with `admin` / ` admin`. # Building the Image If you prefer to build the Peregrine image yourself, simply run: + $ ./travis-build.sh $ cd docker - $ ./builddocker.sh + $ ./builddocker.sh #local + $ ./builddocker-remote-replication.sh #author and publish Launch the locally built docker image + $ docker run -it -p 8080:8080 peregrinecms/peregrine-cms:latest +or for the remote (author/publish) use-case + + $ docker run -d --rm -p 8080:8080 --name peregrine-author peregrinecms/peregrine-cms:latest-author + $ docker run -d --rm -p 8180:8080 --name peregrine-publish peregrinecms/peregrine-cms:latest-publish + # Verifying Container Startup The Peregrine Docker image implements the `HEALTHCHECK` instruction to determine if all diff --git a/docker/builddocker-remote-replication.sh b/docker/builddocker-remote-replication.sh new file mode 100755 index 0000000000..da18bf5add --- /dev/null +++ b/docker/builddocker-remote-replication.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +./builddocker.sh author,notshared author +./builddocker.sh publish,notshared publish + diff --git a/docker/builddocker.sh b/docker/builddocker.sh index e1c3fdc009..e937368dd4 100755 --- a/docker/builddocker.sh +++ b/docker/builddocker.sh @@ -7,4 +7,13 @@ ./fetchfiles.sh -docker build --no-cache --tag=${DOCKER_IMAGE} . +export RUNMODE=$1 +export DOCKER_IMAGE_WITH_TYPE=${DOCKER_IMAGE}-$2 +if [ -z "$1" ] + then + export RUNMODE=none + export DOCKER_IMAGE_WITH_TYPE=${DOCKER_IMAGE} +fi + +echo build docker image for runmode ${RUNMODE} using tag ${DOCKER_IMAGE_WITH_TYPE} +docker build --tag=${DOCKER_IMAGE_WITH_TYPE} --build-arg runmode=$RUNMODE . diff --git a/docker/pushdocker-travis.sh b/docker/pushdocker-travis.sh index 1f5beea42b..e3a3250212 100755 --- a/docker/pushdocker-travis.sh +++ b/docker/pushdocker-travis.sh @@ -10,5 +10,9 @@ if [ ${TRAVIS_PULL_REQUEST} != "false" ]; then TAG="pr-${TRAVIS_PULL_REQUEST}" docker login -u "$DOCKER_USERNAME" -p "$DOCKER_PASSWORD" docker tag "$DOCKER_IMAGE" "${DOCKER_IMAGE}:${TAG}" + docker tag "$DOCKER_IMAGE-author" "${DOCKER_IMAGE}-author:${TAG}" + docker tag "$DOCKER_IMAGE-publish" "${DOCKER_IMAGE}-publish:${TAG}" docker push ${DOCKER_IMAGE}:${TAG} + docker push ${DOCKER_IMAGE}-author:${TAG} + docker push ${DOCKER_IMAGE}-publish:${TAG} fi diff --git a/docker/scripts/install-peregrine.sh b/docker/scripts/install-peregrine.sh index 40d1f70d06..7301cec613 100755 --- a/docker/scripts/install-peregrine.sh +++ b/docker/scripts/install-peregrine.sh @@ -7,7 +7,7 @@ PACKAGE_DIR=/app/binaries SAVE_PWD=`pwd` echo "Starting Sling for the first time..." -/app/scripts/start.sh +/app/scripts/start.sh $1 echo "Installing Sling Packager" npm install @peregrinecms/slingpackager -g @@ -31,6 +31,19 @@ do slingpackager -v upload --install ${PACKAGE_DIR}/$pkg done +# Wait for Sling to be fully ready again +# added an extra sleep to make sure the last package install is completed (sling jobs may take a bit to run) +sleep 5 +STATUS=$(curl -u admin:admin -s --fail http://localhost:8080/system/console/bundles.json | jq '.s[3:5]' -c) +if [ "$STATUS" != "[0,0]" ]; then + while [ "$STATUS" != "[0,0]" ] + do + echo "Sling still starting. Waiting for all bundles to be ready.." + sleep 5 + STATUS=$(curl -u admin:admin -s --fail http://localhost:8080/system/console/bundles.json | jq '.s[3:5]' -c) + done +fi + #echo "Stopping Peregrine..." #kill `ps -ef | grep org.apache.sling.feature.launcher.jar | grep -v grep | awk '{print $2}'` diff --git a/docker/scripts/start.sh b/docker/scripts/start.sh index 3180eaf19e..aaa327f606 100755 --- a/docker/scripts/start.sh +++ b/docker/scripts/start.sh @@ -1,18 +1,21 @@ #!/bin/bash +echo starting sling with runmode $1 + cd /app/sling && java -jar /app/sling/org.apache.sling.feature.launcher.jar \ - -D sling.runmodes=none \ + -D sling.run.modes=$1 \ -f /app/sling/com.peregrine-cms.sling.launchpad-12-SNAPSHOT-oak_tar_far.far \ -p /app/sling \ -c /app/sling/launcher/cache & # Wait for Sling to fully start up +sleep 5 STATUS=$(curl -u admin:admin -s --fail http://localhost:8080/system/console/bundles.json | jq '.s[3:5]' -c) if [ "$STATUS" != "[0,0]" ]; then while [ "$STATUS" != "[0,0]" ] do echo "Sling still starting. Waiting for all bundles to be ready.." - STATUS=$(curl -u admin:admin -s --fail http://localhost:8080/system/console/bundles.json | jq '.s[3:5]' -c) sleep 5 + STATUS=$(curl -u admin:admin -s --fail http://localhost:8080/system/console/bundles.json | jq '.s[3:5]' -c) done fi diff --git a/docs/public/docker/index.md b/docs/public/docker/index.md index 61cff3118b..93b4248714 100644 --- a/docs/public/docker/index.md +++ b/docs/public/docker/index.md @@ -15,7 +15,9 @@ Linux path (not the mounted folders from Windows). ```bash docker run -it -p 8080:8080 peregrinecms/peregrine-cms:develop-sling12 ``` + this command runs a docker container + - `-it`: log output to stdout in the container is forwarded to your console and console blocks until you hit `ctrl-c` to stop the container - `-p 8080:8080`: Your local port 8080 is forwarded to the container port 8080 @@ -26,6 +28,7 @@ Use your browser to go to Peregrine-CMS () ```bash docker pull peregrinecms/peregrine-cms:develop-sling12 ``` + - `pull`: checks and pulls a new version from docker hub for the docker image ## Check out a PR with docker @@ -43,22 +46,43 @@ docker run -it -p 8080:8080 peregrinecms/peregrine-cms:pr-{number} ```bash docker run -rm -it -p 8080:8080 -p 8000:8000 --name peregrine peregrinecms/peregrine-cms:develop-sling12 ``` + - `--name peregrine`: we give our container a name (use `docker ps` to see all your running docker containers) -- ` -rm`: the additional `-rm` removes the docker container when we stop it and frees the name of the container +- `-rm`: the additional `-rm` removes the docker container when we stop it and frees the name of the container - `-p 8000:8000`: in addition to port 8080, also forward port 8000 to the docker container in a second shell/command line run + ```bash docker exec -it peregrine bash ``` -in the docker container `peregrine` **exec**ute `bash` + +in the docker container `peregrine` **exec**ute `bash` once in the shell in the container run the following commands: -``` + +```bash cd /apps/sling/staticreplication npx httpserver -p 8000 ``` -We change the shell to the location where peregrine stores the html files at replication and then start a nodejs based webserver at that location. +We change the shell to the location where peregrine stores the html files at replication and then start a nodejs based webserver at that location. Use your browser to go to the website () or Peregrine-CMS () + +## Run Peregrine-CMS with an author and publish (stage and live) instance + +```bash +docker run -d --rm --network=host --name peregrine-author peregrinecms/peregrine-cms-author:develop-sling12 +docker run -d --rm -p 8180:8080 --name peregrine-publish peregrinecms/peregrine-cms-publish:develop-sling12 +``` + +> `--network=host` makes the author docker instance use the host +network interface. By default, remote replication in peregrine +expects a publisher to be available on port 8180. + +to stop the instances use + +```bash +docker kill peregrine-author peregrine-publish +``` diff --git a/platform/base/core/src/main/java/com/peregrine/adaption/PerPage.java b/platform/base/core/src/main/java/com/peregrine/adaption/PerPage.java index 99dceac5d7..440bfec1e6 100644 --- a/platform/base/core/src/main/java/com/peregrine/adaption/PerPage.java +++ b/platform/base/core/src/main/java/com/peregrine/adaption/PerPage.java @@ -68,7 +68,4 @@ public interface PerPage * - null if no page was found **/ public PerPage getPrevious(); - - /** Marks the given Page as modified **/ - public void markAsModified(); } diff --git a/platform/base/core/src/main/java/com/peregrine/adaption/impl/PerPageImpl.java b/platform/base/core/src/main/java/com/peregrine/adaption/impl/PerPageImpl.java index f34390be92..70d6db0c7b 100644 --- a/platform/base/core/src/main/java/com/peregrine/adaption/impl/PerPageImpl.java +++ b/platform/base/core/src/main/java/com/peregrine/adaption/impl/PerPageImpl.java @@ -28,16 +28,12 @@ import com.peregrine.adaption.Filter; import com.peregrine.adaption.PerPage; import com.peregrine.adaption.PerPageManager; -import org.apache.sling.api.resource.ModifiableValueMap; import org.apache.sling.api.resource.Resource; import java.util.ArrayList; -import java.util.Calendar; import java.util.List; import static com.peregrine.commons.util.PerConstants.JCR_CONTENT; -import static com.peregrine.commons.util.PerConstants.JCR_LAST_MODIFIED; -import static com.peregrine.commons.util.PerConstants.JCR_LAST_MODIFIED_BY; import static com.peregrine.commons.util.PerConstants.JCR_TITLE; import static com.peregrine.commons.util.PerConstants.PAGE_PRIMARY_TYPE; import static com.peregrine.commons.util.PerConstants.TEMPLATE; @@ -219,21 +215,6 @@ public PerPage getPrevious() { return findPrevious(resource); } - @Override - public void markAsModified() { - Resource resource = getResource(); - String user = resource.getResourceResolver().getUserID(); - Calendar now = Calendar.getInstance(); - // Update Content Properties - ModifiableValueMap properties = getModifiableProperties(); - properties.put(JCR_LAST_MODIFIED_BY, user); - properties.put(JCR_LAST_MODIFIED, now); - // Update Page - properties = resource.adaptTo(ModifiableValueMap.class); - properties.put(JCR_LAST_MODIFIED_BY, user); - properties.put(JCR_LAST_MODIFIED, now); - } - private Resource getLastChild(Resource res) { Iterable children = res.getChildren(); Resource answer = null; diff --git a/platform/base/core/src/main/java/com/peregrine/render/impl/ReferenceListerService.java b/platform/base/core/src/main/java/com/peregrine/reference/impl/ReferenceListerService.java similarity index 62% rename from platform/base/core/src/main/java/com/peregrine/render/impl/ReferenceListerService.java rename to platform/base/core/src/main/java/com/peregrine/reference/impl/ReferenceListerService.java index 67d90bd846..1614d8e94b 100644 --- a/platform/base/core/src/main/java/com/peregrine/render/impl/ReferenceListerService.java +++ b/platform/base/core/src/main/java/com/peregrine/reference/impl/ReferenceListerService.java @@ -1,4 +1,4 @@ -package com.peregrine.render.impl; +package com.peregrine.reference.impl; /*- * #%L @@ -26,8 +26,6 @@ */ import static com.peregrine.commons.util.PerConstants.JCR_CONTENT; -import static com.peregrine.commons.util.PerConstants.SLASH; -import static com.peregrine.commons.util.PerUtil.isEmpty; import static com.peregrine.commons.util.PerUtil.isNotEmpty; import static com.peregrine.commons.util.PerUtil.listMissingParents; import static java.util.Objects.isNull; @@ -37,7 +35,11 @@ import com.peregrine.reference.Reference; import com.peregrine.reference.ReferenceLister; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; @@ -63,9 +65,8 @@ immediate = true ) @Designate(ocd = ReferenceListerService.Configuration.class) -public class ReferenceListerService - implements ReferenceLister -{ +public final class ReferenceListerService implements ReferenceLister { + @ObjectClassDefinition( name = "Peregrine: Reference List Provider", description = "Provides a list of referenced resources for a given resource" @@ -146,7 +147,6 @@ private void checkResource(Resource resource, TraversingContext context, List deepLimits = new TreeSet<>(); - private Tree visited = new Tree(); - - public TraversingContext(final PerUtil.ResourceChecker checker) { - this.checker = isNull(checker) ? PerUtil.ADD_ALL_RESOURCE_CHECKER : checker; - } - - public TraversingContext setTransitive(boolean transitive) { - this.transitive = transitive; - return this; - } - - public TraversingContext setDeep(boolean deep) { - this.deep = deep; - return this; - } - - /** @return True if references in references should be listed as well **/ - public boolean isTransitive() { - return transitive; - } - - /** @return True if all children are traversed **/ - public boolean isDeep() { - return deep; - } - - /** - * Checks the resource if it should be checked. If will not - * be checked if not deep but outside of the marked deep paths - * or if already visited. If not visited then this method will - * add them to the visited list - * @param resource Resource to be checked - * @return TRUE if we are going deep and are not visited yet or - * are in the deep limited paths and not visited yet - */ - public boolean proceed(Resource resource) { - if(resource != null) { - String path = resource.getPath(); - if(!visited.contains(path) && checker.doAdd(resource)) { - visited.addChildByPath(path); - if(!checker.doAddChildren(resource)) { - return false; - } - if(!deep) { - for(String limit : deepLimits) { - if(path.startsWith(limit)) { - return true; - } - } - } else { - return true; - } - } - } - return false; - } - - /** - * Adds an exempt starting path if traversing is not deep - * @param path Exempt path to be added. In order to make this work the value - * must start with a slash - */ - public TraversingContext addDeepLimit(String path) { - if(isNotEmpty(path) && !deepLimits.contains(path)) { - deepLimits.add(path); - } - return this; - } - - @Override - public boolean doAdd(Resource resource) { - return checker.doAdd(resource); - } - - @Override - public boolean doAddChildren(Resource resource) { - return checker.doAddChildren(resource); - } - - } - - /** - * Root Object of a Folder Name Base Tree. It allows to - * add children by a JCR Node Path - **/ - public static class Tree - extends Node - { - public Tree() { - super(null, SLASH); - } - - void setParent(Node parent) {} - - /** - * Checks if the given path exists in this tree - * @param path JCR Resource Path to be checked - * @return True if for all JCR resources of the path there is a corresponding node - */ - public boolean contains(String path) { - boolean answer = false; - if(isNotEmpty(path)) { - answer = true; - String[] tokens = path.split(SLASH); - Node node = this; - for(String token: tokens) { - if(isNotEmpty(token)) { - Node child = node.getChild(token); - if(child != null) { - node = child; - } else { - answer = false; - break; - } - } - } - } - return answer; - } - - /** - * Creates a node for a resources in the given path if they don't already exist - * @param path JCR Resource Path separated by a slash - * @return This tree instance - */ - public Tree addChildByPath(String path) { - if(isEmpty(path)) { throw new IllegalArgumentException("Child Path must be provided"); } - String[] tokens = path.split(SLASH); - Node node = this; - for(String token: tokens) { - if(isNotEmpty(token)) { - Node child = node.getChild(token); - if(child != null) { - node = child; - } else { - node = node.addChild(token); - } - } - } - return this; - } - - @Override - public String toString() { - return "Tree(" + super.toString() + ")"; - } - } - - /** - * Node Entry of the Folder Tree - * This represents a JCR Resource in a path - */ - public static class Node { - private String segment; - private List children; - - /** - * Creates a node with a given parent and name - * @param parent Parent Node of this node. This node will be added as child to this parent here - * @param segment Resource Name - */ - public Node(Node parent, String segment) { - setParent(parent); - if(isEmpty(segment)) { - throw new IllegalArgumentException("Node Segment must be defined"); - } - this.segment = segment; - } - - /** Resource Name **/ - public String getSegment() { - return segment; - } - - /** - * Sets the given Node as parent and adds itself as child to that parent ** - * @parent Parent Node which cannot be null - */ - void setParent(Node parent) { - if(parent == null) { throw new IllegalArgumentException("Parent Node must be defined"); } - parent.addChild(this); - } - - /** @return A node with the given resource name if found otherwise null **/ - public Node getChild(String segment) { - Node answer = null; - if(children != null && isNotEmpty(segment)) { - for(Node child: children) { - if(child.getSegment().equals(segment)) { - answer = child; - break; - } - } - } - return answer; - } - - /** - * Adds the given Node as child - * @param child Node to be added as child which cannot be null - * @return Child node which is either the given one or the one that is already added as child with that resource name - */ - public Node addChild(Node child) { - if(child == null) { throw new IllegalArgumentException("Cannot add undefined child"); } - if(children == null) { children = new ArrayList<>(); } - Node myChild = getChild(child.segment); - if(myChild == null) { - children.add(child); - return child; - } else { - return myChild; - } - } - - /** - * Creates a new child and adds it as child to this node as parent - * @param segment Resource Name of the new child - * @return Node that was created and added if not found otherwise the child with the given resource name - */ - public Node addChild(String segment) { - Node child = getChild(segment); - if(child == null) { - child = new Node(this, segment); - } - return child; - } - - @Override - public String toString() { - return "Node(" + segment + ") {" + (children == null ? "" : children.toString()) + "}"; - } - } } diff --git a/platform/base/core/src/main/java/com/peregrine/reference/impl/TraversingContext.java b/platform/base/core/src/main/java/com/peregrine/reference/impl/TraversingContext.java new file mode 100644 index 0000000000..65110dd26e --- /dev/null +++ b/platform/base/core/src/main/java/com/peregrine/reference/impl/TraversingContext.java @@ -0,0 +1,55 @@ +package com.peregrine.reference.impl; + +import com.peregrine.commons.util.PerUtil; +import org.apache.sling.api.resource.Resource; + +import static java.util.Objects.isNull; + +/** + * Traversing context providing necessary flags as well as defining which resource are processed + * It also makes sure that we don't end up in an endless loop with cyclic references + **/ +class TraversingContext implements PerUtil.ResourceChecker { + private final PerUtil.ResourceChecker checker; + private boolean transitive = false; + private boolean deep = false; + + public TraversingContext(final PerUtil.ResourceChecker checker) { + this.checker = isNull(checker) ? PerUtil.ADD_ALL_RESOURCE_CHECKER : checker; + } + + public TraversingContext setTransitive(boolean transitive) { + this.transitive = transitive; + return this; + } + + public TraversingContext setDeep(boolean deep) { + this.deep = deep; + return this; + } + + /** + * @return True if references in references should be listed as well + **/ + public boolean isTransitive() { + return transitive; + } + + /** + * @return True if all children are traversed + **/ + public boolean isDeep() { + return deep; + } + + @Override + public boolean doAdd(Resource resource) { + return checker.doAdd(resource); + } + + @Override + public boolean doAddChildren(Resource resource) { + return checker.doAddChildren(resource); + } + +} diff --git a/platform/base/core/src/main/java/com/peregrine/rendition/BaseResourceHandlerService.java b/platform/base/core/src/main/java/com/peregrine/rendition/BaseResourceHandlerService.java index f3d3bd6b3c..b94013f12c 100644 --- a/platform/base/core/src/main/java/com/peregrine/rendition/BaseResourceHandlerService.java +++ b/platform/base/core/src/main/java/com/peregrine/rendition/BaseResourceHandlerService.java @@ -34,6 +34,7 @@ import static com.peregrine.commons.util.PerConstants.JCR_LAST_MODIFIED_BY; import static com.peregrine.commons.util.PerConstants.PNG_MIME_TYPE; import static com.peregrine.commons.util.PerUtil.getModifiableProperties; +import static java.util.Objects.isNull; /** * Created by Andreas Schaefer on 7/6/17. @@ -197,24 +198,22 @@ public void updateModification(ResourceResolver resourceResolver, Node node) { /** @param resource Adds / Update the Last Modified and Last Modified By property on this resource **/ @Override - public void updateModification(Resource resource) { - if(resource != null) { - String user = resource.getResourceResolver().getUserID(); - Calendar now = Calendar.getInstance(); - ModifiableValueMap properties = getModifiableProperties(resource, false); + public void updateModification(final Resource resource) { + if (isNull(resource)) { + return; + } + + String user = resource.getResourceResolver().getUserID(); + Calendar now = Calendar.getInstance(); + final Resource base = PerUtil.getBaseResource(resource); + ModifiableValueMap properties = getModifiableProperties(base, false); + properties.put(JCR_LAST_MODIFIED_BY, user); + properties.put(JCR_LAST_MODIFIED, now); + Resource jcrContent = PerUtil.getProperJcrContent(base); + if (jcrContent != null) { + properties = getModifiableProperties(jcrContent, false); properties.put(JCR_LAST_MODIFIED_BY, user); properties.put(JCR_LAST_MODIFIED, now); - PerPage page = resource.adaptTo(PerPage.class); - if(page != null) { - page.markAsModified(); - } else { - Resource jcrContent = PerUtil.getResource(resource, JCR_CONTENT); - if(jcrContent != null) { - properties = getModifiableProperties(jcrContent, false); - properties.put(JCR_LAST_MODIFIED_BY, user); - properties.put(JCR_LAST_MODIFIED, now); - } - } } } } diff --git a/platform/base/ui.apps/pom.xml b/platform/base/ui.apps/pom.xml index 215c801667..31a4188bc7 100644 --- a/platform/base/ui.apps/pom.xml +++ b/platform/base/ui.apps/pom.xml @@ -53,6 +53,11 @@ login ${project.version} + + ${project.groupId} + distribution + ${project.version} + @@ -115,6 +120,11 @@ login true + + ${project.groupId} + distribution + true + diff --git a/platform/commons/src/main/java/com/peregrine/commons/util/PerUtil.java b/platform/commons/src/main/java/com/peregrine/commons/util/PerUtil.java index c7145c5471..3658a709ef 100644 --- a/platform/commons/src/main/java/com/peregrine/commons/util/PerUtil.java +++ b/platform/commons/src/main/java/com/peregrine/commons/util/PerUtil.java @@ -386,6 +386,22 @@ public static ValueMap getJcrContentOrSelfProperties(final Resource resource) { .orElse(null); } + /** + * We define the notion of a base for a given resource here as the parent of + * jcr:content or the resource itself otherwise. + * + * @param resource the resource for which we want to extract the base + * @return the parent resource, if the resource is jcr:content, + * or the resource itself otherwise (it's its own base then) + */ + public static Resource getBaseResource(final Resource resource) { + if (isJcrContent(resource)) { + return resource.getParent(); + } + + return resource; + } + /** * Gets the Modifiable Value Map of the Resource JCR Content * diff --git a/platform/distribution/pom.xml b/platform/distribution/pom.xml index d560ad6b19..63d206a7be 100644 --- a/platform/distribution/pom.xml +++ b/platform/distribution/pom.xml @@ -163,7 +163,7 @@ - autoInstallPackage + autoInstallBundle @@ -181,23 +181,5 @@ - - installAEM - - - - - org.apache.sling - maven-sling-plugin - - - install-bundle - none - - - - - - diff --git a/pom.xml b/pom.xml index d9acc7b3b5..9287cd04df 100644 --- a/pom.xml +++ b/pom.xml @@ -516,7 +516,7 @@ org.apache.jackrabbit.vault org.apache.jackrabbit.vault - 3.4.8 + 3.4.10 provided diff --git a/travis-build.sh b/travis-build.sh index 7e56d216d3..53c6bd34d9 100755 --- a/travis-build.sh +++ b/travis-build.sh @@ -9,8 +9,8 @@ mvn clean install #cd ../.. echo "Fetching Peregrine CMS Feature Launcher..." -curl -L -o ./docker/files/com.peregrine-cms.sling.launchpad-12-SNAPSHOT-oak_tar_far.far https://github.com/peregrine-cms/peregrine-builder/releases/download/0.0.3/com.peregrine-cms.sling.launchpad-12-SNAPSHOT-oak_tar_far.far -curl -L -o ./docker/files/org.apache.sling.feature.launcher.jar https://github.com/peregrine-cms/peregrine-builder/releases/download/0.0.3/org.apache.sling.feature.launcher.jar +curl -L -o ./docker/files/com.peregrine-cms.sling.launchpad-12-SNAPSHOT-oak_tar_far.far https://github.com/peregrine-cms/peregrine-builder/releases/download/0.0.6/com.peregrine-cms.sling.launchpad-12-SNAPSHOT-oak_tar_far.far +curl -L -o ./docker/files/org.apache.sling.feature.launcher.jar https://github.com/peregrine-cms/peregrine-builder/releases/download/0.0.6/org.apache.sling.feature.launcher.jar echo "Building 'themeclean-flex'..." git clone https://github.com/headwirecom/themeclean-flex