Skip to content

Commit

Permalink
Merge pull request #22 from orbinson/feature/unpublish-deleted-labels
Browse files Browse the repository at this point in the history
resolves #21: Unpublish labels / dictionaries / languages before dele…
  • Loading branch information
royteeuwen authored Feb 28, 2024
2 parents b5a855b + b48075b commit 24a826f
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 52 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package be.orbinson.aem.dictionarytranslator.servlets.action;

import com.day.cq.replication.ReplicationActionType;
import com.day.cq.replication.ReplicationException;
import com.day.cq.replication.Replicator;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
Expand All @@ -10,9 +13,11 @@
import org.apache.sling.servlets.annotations.SlingServletResourceTypes;
import org.jetbrains.annotations.NotNull;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.Session;
import javax.servlet.Servlet;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
Expand All @@ -25,27 +30,30 @@
)
public class DeleteDictionaryServlet extends SlingAllMethodsServlet {
private static final Logger LOG = LoggerFactory.getLogger(DeleteDictionaryServlet.class);
public static final String DICTIONARIES_PARAM = "dictionaries";

@Reference
private transient Replicator replicator;

@Override
protected void doPost(SlingHttpServletRequest request, @NotNull SlingHttpServletResponse response) throws IOException {
String dictionaries = request.getParameter("dictionaries");
String dictionaries = request.getParameter(DICTIONARIES_PARAM);

if (StringUtils.isNotEmpty(dictionaries)) {
final ResourceResolver resourceResolver = request.getResourceResolver();

for (String dictionary : dictionaries.split(",")) {
final Resource resource = resourceResolver.getResource(dictionary);
if (resource != null) {
LOG.debug("Delete dictionary '{}'", dictionary);
resourceResolver.delete(resource);
} else {
LOG.warn("Dictionary '{}' not found to delete", dictionary);
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}

try {
resourceResolver.commit();
} catch (PersistenceException e) {
final Resource resource = resourceResolver.getResource(dictionary);
if (resource != null) {
LOG.debug("Delete dictionary '{}'", dictionary);
deactivateAndDelete(resourceResolver, resource);
resourceResolver.commit();
} else {
LOG.warn("Dictionary '{}' not found to delete", dictionary);
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
} catch (PersistenceException | ReplicationException e) {
LOG.error("Error deleting item: {}", dictionary, e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
}
Expand All @@ -55,4 +63,9 @@ protected void doPost(SlingHttpServletRequest request, @NotNull SlingHttpServlet
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
}
}

private void deactivateAndDelete(ResourceResolver resourceResolver, Resource resource) throws ReplicationException, PersistenceException {
replicator.replicate(resourceResolver.adaptTo(Session.class), ReplicationActionType.DEACTIVATE, resource.getPath());
resourceResolver.delete(resource);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package be.orbinson.aem.dictionarytranslator.servlets.action;

import com.day.cq.replication.ReplicationActionType;
import com.day.cq.replication.ReplicationException;
import com.day.cq.replication.Replicator;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
Expand All @@ -10,9 +13,11 @@
import org.apache.sling.servlets.annotations.SlingServletResourceTypes;
import org.jetbrains.annotations.NotNull;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.Session;
import javax.servlet.Servlet;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
Expand All @@ -25,10 +30,14 @@
)
public class DeleteLabelServlet extends SlingAllMethodsServlet {
private static final Logger LOG = LoggerFactory.getLogger(DeleteLabelServlet.class);
public static final String LABELS_PARAM = "labels";

@Reference
private transient Replicator replicator;

@Override
protected void doPost(SlingHttpServletRequest request, @NotNull SlingHttpServletResponse response) throws IOException {
String labels = request.getParameter("labels");
String labels = request.getParameter(LABELS_PARAM);

if (StringUtils.isEmpty(labels)) {
LOG.warn("Labels parameters are required");
Expand All @@ -41,17 +50,22 @@ protected void doPost(SlingHttpServletRequest request, @NotNull SlingHttpServlet
if (resource != null) {
// javasecurity:S5145
LOG.debug("Delete label on path '{}'", labels);
resourceResolver.delete(resource);
deactivateAndDelete(resourceResolver, resource);
} else {
// javasecurity:S5145
LOG.warn("Unable to get label '{}'", labels);
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
}
} catch (PersistenceException e) {
} catch (PersistenceException | ReplicationException e) {
LOG.error("Unable to delete labels '{}'", labels);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
}
}

private void deactivateAndDelete(ResourceResolver resourceResolver, Resource resource) throws ReplicationException, PersistenceException {
replicator.replicate(resourceResolver.adaptTo(Session.class), ReplicationActionType.DEACTIVATE, resource.getPath());
resourceResolver.delete(resource);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package be.orbinson.aem.dictionarytranslator.servlets.action;

import com.day.cq.replication.ReplicationActionType;
import com.day.cq.replication.ReplicationException;
import com.day.cq.replication.Replicator;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
Expand All @@ -10,9 +13,11 @@
import org.apache.sling.servlets.annotations.SlingServletResourceTypes;
import org.jetbrains.annotations.NotNull;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.Session;
import javax.servlet.Servlet;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
Expand All @@ -25,12 +30,17 @@
)
public class DeleteLanguageServlet extends SlingAllMethodsServlet {
private static final Logger LOG = LoggerFactory.getLogger(DeleteLanguageServlet.class);
public static final String LANGUAGE_PARAM = "language";
public static final String DICTIONARY_PARAM = "dictionary";

@Reference
private transient Replicator replicator;

@Override
@SuppressWarnings("java:S1075")
public void doPost(SlingHttpServletRequest request, @NotNull SlingHttpServletResponse response) throws IOException {
final String language = request.getParameter("language");
final String dictionary = request.getParameter("dictionary");
final String language = request.getParameter(LANGUAGE_PARAM);
final String dictionary = request.getParameter(DICTIONARY_PARAM);

if (StringUtils.isNotEmpty(dictionary) && StringUtils.isNotEmpty(language)) {
ResourceResolver resourceResolver = request.getResourceResolver();
Expand All @@ -40,13 +50,13 @@ public void doPost(SlingHttpServletRequest request, @NotNull SlingHttpServletRes
try {
if (resource != null) {
LOG.debug("Delete language '{}' from '{}'", language, dictionary);
resourceResolver.delete(resource);
deactivateAndDelete(resourceResolver, resource);
resourceResolver.commit();
} else {
LOG.warn("Unable to find dictionary '{}'", path);
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
}
} catch (PersistenceException e) {
} catch (PersistenceException | ReplicationException e) {
LOG.error("Unable to delete language '{}' from dictionary '{}'", language, dictionary);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
Expand All @@ -55,4 +65,9 @@ public void doPost(SlingHttpServletRequest request, @NotNull SlingHttpServletRes
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
}
}

private void deactivateAndDelete(ResourceResolver resourceResolver, Resource resource) throws ReplicationException, PersistenceException {
replicator.replicate(resourceResolver.adaptTo(Session.class), ReplicationActionType.DEACTIVATE, resource.getPath());
resourceResolver.delete(resource);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.distribution.Distributor;
import org.apache.sling.servlets.annotations.SlingServletResourceTypes;
import org.jetbrains.annotations.NotNull;
import org.osgi.service.component.annotations.Component;
Expand All @@ -32,9 +31,6 @@ public class ReplicateDictionaryServlet extends SlingAllMethodsServlet {

private static final Logger LOG = LoggerFactory.getLogger(ReplicateDictionaryServlet.class);

@Reference
private transient Distributor distributor;

@Reference
private transient Replicator replicator;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,42 @@
package be.orbinson.aem.dictionarytranslator.servlets.action;

import com.day.cq.replication.ReplicationActionType;
import com.day.cq.replication.ReplicationException;
import com.day.cq.replication.Replicator;
import io.wcm.testing.mock.aem.junit5.AemContext;
import io.wcm.testing.mock.aem.junit5.AemContextExtension;
import org.apache.sling.testing.mock.sling.ResourceResolverType;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import javax.jcr.Session;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

@ExtendWith({AemContextExtension.class})
@ExtendWith({AemContextExtension.class, MockitoExtension.class})
class DeleteDictionaryServletTest {
private final AemContext context = new AemContext();
private final AemContext context = new AemContext(ResourceResolverType.JCR_MOCK);

DeleteDictionaryServlet servlet;

@Mock
Replicator replicator;

@BeforeEach
void beforeEach() {
servlet = context.registerService(new DeleteDictionaryServlet());
replicator = context.registerService(Replicator.class, replicator);
servlet = context.registerInjectActivateService(new DeleteDictionaryServlet());
}

@Test
Expand All @@ -36,31 +50,35 @@ void doPostWithoutParams() throws ServletException, IOException {
}

@Test
@Disabled("Temporary disabled to test CI")
void deleteExistingDictionary() throws ServletException, IOException {
context.create().resource("/content/dictionaries/site-a/i18n");
context.create().resource("/content/dictionaries/site-b/i18n");
void deleteExistingDictionary() throws ServletException, IOException, ReplicationException {
String dictionaryToDelete = "/content/dictionaries/site-a/i18n";
context.create().resource(dictionaryToDelete);
String dictionaryToKeep = "/content/dictionaries/site-b/i18n";
context.create().resource(dictionaryToKeep);
context.request().setMethod("POST");
context.request().setParameterMap(Map.of(
"dictionary", new String[]{"/content/dictionaries/site-a/i18n"}
DeleteDictionaryServlet.DICTIONARIES_PARAM, new String[]{dictionaryToDelete}
));

servlet.service(context.request(), context.response());

assertNull(context.resourceResolver().getResource("/content/dictionaries/site-a/i18n"));
assertNotNull(context.resourceResolver().getResource("/content/dictionaries/site-b/i18n"));
assertNull(context.resourceResolver().getResource(dictionaryToDelete));
verify(replicator).replicate(any(Session.class), eq(ReplicationActionType.DEACTIVATE), eq(dictionaryToDelete));

assertNotNull(context.resourceResolver().getResource(dictionaryToKeep));
verify(replicator, times(0)).replicate(any(Session.class), eq(ReplicationActionType.DEACTIVATE), eq(dictionaryToKeep));

assertEquals(HttpServletResponse.SC_OK, context.response().getStatus());
}

@Test
@Disabled("Temporary disabled to test CI")
void deleteMultipleDictionaries() throws ServletException, IOException {
context.create().resource("/content/dictionaries/site-a/i18n");
context.create().resource("/content/dictionaries/site-b/i18n");
context.create().resource("/content/dictionaries/site-c/i18n");
context.request().setMethod("POST");
context.request().setParameterMap(Map.of(
"dictionary", new String[]{"/content/dictionaries/site-a/i18n,/content/dictionaries/site-b/i18n"}
DeleteDictionaryServlet.DICTIONARIES_PARAM, new String[]{"/content/dictionaries/site-a/i18n,/content/dictionaries/site-b/i18n"}
));

servlet.service(context.request(), context.response());
Expand All @@ -72,12 +90,11 @@ void deleteMultipleDictionaries() throws ServletException, IOException {
}

@Test
@Disabled("Temporary disabled to test CI")
void deleteNonExistingDictionary() throws ServletException, IOException {
context.create().resource("/content/dictionaries/site-a/i18n");
context.request().setMethod("POST");
context.request().setParameterMap(Map.of(
"dictionary", new String[]{"/content/dictionaries/site-b/i18n"}
DeleteDictionaryServlet.DICTIONARIES_PARAM, new String[]{"/content/dictionaries/site-b/i18n"}
));

servlet.service(context.request(), context.response());
Expand Down
Loading

0 comments on commit 24a826f

Please sign in to comment.