Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use JcrPackageDefinition for retrieving metadata #3227

Merged
merged 3 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com)

## Unreleased ([details][unreleased changes details])

- #3225 - PackageGarbageCollector leaves temp files behind
- #3187 - Remove warning during build on Java 11 or higher when DialogProviderAnnotationProcessor is invoked
- #3242 - Actually update lodash to 4.17.21 (was mistakenly updated to 4.17.15 instead of 4.17.21)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,26 @@
*/
package com.adobe.acs.commons.packagegarbagecollector;

import org.apache.jackrabbit.JcrConstants;
import static com.adobe.acs.commons.packagegarbagecollector.PackageGarbageCollectionScheduler.GROUP_NAME;
import static com.adobe.acs.commons.packagegarbagecollector.PackageGarbageCollectionScheduler.MAX_AGE_IN_DAYS;
import static com.adobe.acs.commons.packagegarbagecollector.PackageGarbageCollectionScheduler.REMOVE_NOT_INSTALLED_PACKAGES;

import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

import javax.jcr.RepositoryException;
import javax.jcr.Session;

import org.apache.jackrabbit.vault.packaging.JcrPackage;
import org.apache.jackrabbit.vault.packaging.JcrPackageDefinition;
import org.apache.jackrabbit.vault.packaging.JcrPackageManager;
Expand All @@ -35,24 +54,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;

import static com.adobe.acs.commons.packagegarbagecollector.PackageGarbageCollectionScheduler.*;

@Component(
service = JobConsumer.class,
immediate = true,
Expand Down Expand Up @@ -87,24 +88,30 @@
JcrPackageManager packageManager = packaging.getPackageManager(session);
List<JcrPackage> packages = packageManager.listPackages(groupName, false);

for (JcrPackage jcrPackage : packages) {
String packageDescription = getPackageDescription(jcrPackage);
LOG.info("Processing package {}", packageDescription);

if (isPackageOldEnough(jcrPackage, maxAgeInDays)) {
if (removeNotInstalledPackages && !isInstalled(jcrPackage)) {
packageManager.remove(jcrPackage);
packagesRemoved++;
LOG.info("Deleted not-installed package {}", packageDescription);
} else if (isInstalled(jcrPackage) && !isLatestInstalled(jcrPackage, packageManager.listPackages(groupName, false))) {
packageManager.remove(jcrPackage);
packagesRemoved++;
LOG.info("Deleted installed package {} since it is not the latest installed version.", packageDescription);
for (JcrPackage tmpPackage : packages) {
try (JcrPackage jcrPackage = tmpPackage) {
JcrPackageDefinition definition = jcrPackage.getDefinition();

Check warning on line 93 in bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java

View check run for this annotation

Codecov / codecov/patch

bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java#L92-L93

Added lines #L92 - L93 were not covered by tests
if (definition == null) {
LOG.warn("Skipping package without definition: {}", jcrPackage.getNode().getPath());

Check warning on line 95 in bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java

View check run for this annotation

Codecov / codecov/patch

bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java#L95

Added line #L95 was not covered by tests
}
String packageDescription = getPackageDescription(definition);
LOG.info("Processing package {}", packageDescription);

Check warning on line 98 in bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java

View check run for this annotation

Codecov / codecov/patch

bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java#L97-L98

Added lines #L97 - L98 were not covered by tests

if (isPackageOldEnough(definition, maxAgeInDays)) {
if (removeNotInstalledPackages && !isInstalled(definition)) {
packageManager.remove(jcrPackage);
packagesRemoved++;
LOG.info("Deleted not-installed package {}", packageDescription);

Check warning on line 104 in bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java

View check run for this annotation

Codecov / codecov/patch

bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java#L102-L104

Added lines #L102 - L104 were not covered by tests
} else if (isInstalled(definition) && !isLatestInstalled(definition, packageManager.listPackages(groupName, false).stream())) {
packageManager.remove(jcrPackage);
packagesRemoved++;
LOG.info("Deleted installed package {} since it is not the latest installed version.", packageDescription);

Check warning on line 108 in bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java

View check run for this annotation

Codecov / codecov/patch

bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java#L106-L108

Added lines #L106 - L108 were not covered by tests
} else {
LOG.info("Not removing package because it's the current installed one {}", packageDescription);

Check warning on line 110 in bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java

View check run for this annotation

Codecov / codecov/patch

bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java#L110

Added line #L110 was not covered by tests
}
} else {
LOG.info("Not removing package because it's the current installed one {}", packageDescription);
LOG.debug("Not removing package because it's not old enough {}", packageDescription);

Check warning on line 113 in bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java

View check run for this annotation

Codecov / codecov/patch

bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java#L113

Added line #L113 was not covered by tests
}
} else {
LOG.debug("Not removing package because it's not old enough {}", packageDescription);
}
}
} catch (LoginException | RepositoryException | IOException e) {
Expand All @@ -118,120 +125,84 @@
return JobResult.OK;
}

private boolean isInstalled(JcrPackage jcrPackage) {
PackageDefinition definition = new PackageDefinition(jcrPackage);
return definition.getLastUnpacked() != null;
private boolean isInstalled(JcrPackageDefinition pkgDefinition) {
return pkgDefinition.getLastUnpacked() != null;
}

private boolean isLatestInstalled(JcrPackage jcrPackage, List<JcrPackage> installedPackages) {
Optional<JcrPackage> lastInstalledPackageOptional = installedPackages.stream().filter(installedPackage -> {
PackageDefinition definition = new PackageDefinition(installedPackage);
return definition.isSameNameAndGroup(jcrPackage);
})
.filter(pkg -> new PackageDefinition(pkg).getLastUnpacked() != null)
.max(Comparator.comparing(pkg -> new PackageDefinition(pkg).getLastUnpacked()));

if (lastInstalledPackageOptional.isPresent()) {
JcrPackage lastInstalledPackage = lastInstalledPackageOptional.get();
PackageDefinition lastInstalledPackageDefinition = new PackageDefinition(lastInstalledPackage);
PackageDefinition thisPackageDefinition = new PackageDefinition(jcrPackage);
private static final class UncheckedRepositoryException extends RuntimeException {
private static final long serialVersionUID = 8851421623772855854L;

// If it's not actually installed yet.
if (lastInstalledPackageDefinition.getLastUnpacked() == null) {
// This should never be here since this check is guarded by isInstalled() above.
return false;
}
protected UncheckedRepositoryException(RepositoryException e) {
super(e);
}

Check warning on line 137 in bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java

View check run for this annotation

Codecov / codecov/patch

bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java#L136-L137

Added lines #L136 - L137 were not covered by tests

return lastInstalledPackageDefinition.hasSamePid(thisPackageDefinition);
/**
* Returns the cause of this exception.
*
* @return the {@code RepositoryException} which is the cause of this exception.
*/
@Override
public RepositoryException getCause() {
return (RepositoryException) super.getCause();

Check warning on line 146 in bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java

View check run for this annotation

Codecov / codecov/patch

bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java#L146

Added line #L146 was not covered by tests
}

return false;
}

static class PackageDefinition {
JcrPackage jcrPackage;

public PackageDefinition(@Nonnull JcrPackage jcrPackage) {
this.jcrPackage = jcrPackage;
}

public Calendar getLastUnpacked() {
try {
JcrPackageDefinition definition = jcrPackage.getDefinition();
if (definition != null) {
return definition.getLastUnpacked();
}
return null;
} catch (RepositoryException ex) {
return null;
}
}
private boolean isLatestInstalled(JcrPackageDefinition referencePkgDefinition, Stream<JcrPackage> installedPackages) throws RepositoryException {
try {
Optional<JcrPackageDefinition> lastInstalledPckDefinitionOptional = installedPackages
.map(p -> {

Check warning on line 154 in bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java

View check run for this annotation

Codecov / codecov/patch

bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java#L153-L154

Added lines #L153 - L154 were not covered by tests
try {
return p.getDefinition();
} catch (RepositoryException e) {

Check warning on line 157 in bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java

View check run for this annotation

Codecov / codecov/patch

bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java#L156-L157

Added lines #L156 - L157 were not covered by tests
String pckPath;
try {
pckPath = p.getNode().getPath();
} catch (RepositoryException nestedException) {
pckPath = "Unknown";
}
throw new UncheckedRepositoryException(new RepositoryException("Cannot read package definition of package " + pckPath, e));

Check warning on line 164 in bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java

View check run for this annotation

Codecov / codecov/patch

bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java#L160-L164

Added lines #L160 - L164 were not covered by tests
}
})
.filter(def -> isSameNameAndGroup(referencePkgDefinition.getId(), def.getId()))

Check warning on line 167 in bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java

View check run for this annotation

Codecov / codecov/patch

bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java#L167

Added line #L167 was not covered by tests
.filter(def -> def.getLastUnpacked() != null)
.max(Comparator.comparing(def -> def.getLastUnpacked()));

Check warning on line 169 in bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java

View check run for this annotation

Codecov / codecov/patch

bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java#L169

Added line #L169 was not covered by tests

public boolean isSameNameAndGroup(JcrPackage otherPackage) {
Optional<PackageId> otherPackageId = getPid(otherPackage);
Optional<PackageId> thisPackageId = getPid(jcrPackage);
if (otherPackageId.isPresent() && thisPackageId.isPresent()) {
return otherPackageId.get().getGroup().equals(thisPackageId.get().getGroup())
&& otherPackageId.get().getName().equals(thisPackageId.get().getName());
if (lastInstalledPckDefinitionOptional.isPresent()) {
return lastInstalledPckDefinitionOptional.get().getId().equals(referencePkgDefinition.getId());

Check warning on line 172 in bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java

View check run for this annotation

Codecov / codecov/patch

bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java#L172

Added line #L172 was not covered by tests
}
return false;
} catch (UncheckedRepositoryException e) {
throw e.getCause();

Check warning on line 176 in bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java

View check run for this annotation

Codecov / codecov/patch

bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java#L175-L176

Added lines #L175 - L176 were not covered by tests
}
}

public PackageId getId() {
try {
JcrPackageDefinition definition = jcrPackage.getDefinition();
if (definition != null) {
return definition.getId();
}
return null;
} catch (RepositoryException ex) {
return null;
}
}

private Optional<PackageId> getPid(JcrPackage jcrPkg) {
try {
return Optional.ofNullable(jcrPkg.getDefinition()).map(JcrPackageDefinition::getId);
} catch (RepositoryException ex) {
return Optional.empty();
}
}

public boolean hasSamePid(PackageDefinition jcrPkg) {
try {
Optional<PackageId> pkgId = Optional.ofNullable(jcrPkg.getId());
return pkgId.map(packageId -> packageId.equals(getId())).orElse(false);
} catch (NullPointerException ex) {
return false;
}
}
public static boolean isSameNameAndGroup(PackageId thisPackageId, PackageId otherPackageId){
return otherPackageId.getGroup().equals(thisPackageId.getGroup())
&& otherPackageId.getName().equals(thisPackageId.getName());
}

private boolean isPackageOldEnough(JcrPackage jcrPackage, Integer maxAgeInDays) throws RepositoryException, IOException {
private boolean isPackageOldEnough(JcrPackageDefinition pkgDefinition, Integer maxAgeInDays) throws RepositoryException, IOException {
Period maxAge = Period.ofDays(maxAgeInDays);
LocalDate oldestAge = LocalDate.now().minus(maxAge);
Calendar packageCreatedAtCalendar = jcrPackage.getPackage().getCreated();
final Calendar packageCreatedAtCalendar;

try {
packageCreatedAtCalendar = pkgDefinition.getCreated();

Check warning on line 191 in bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java

View check run for this annotation

Codecov / codecov/patch

bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java#L191

Added line #L191 was not covered by tests
if (packageCreatedAtCalendar == null) {
// Try getting the created at directly from the JCR node that represents the package.
packageCreatedAtCalendar = jcrPackage.getDefinition().getNode().getProperty(JcrConstants.JCR_CREATED).getValue().getDate();

if (packageCreatedAtCalendar == null) {
// This should not happen, but if it does, we don't want to delete the package.
LOG.warn("Package [ {} ] has no created date, assuming it's NOT old enough", jcrPackage.getNode().getPath());
return false;
}
// This should not happen, but if it does, we don't want to delete the package.
LOG.warn("Package [ {} ] has no created date, assuming it's NOT old enough", pkgDefinition.getNode().getPath());
return false;

Check warning on line 195 in bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java

View check run for this annotation

Codecov / codecov/patch

bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java#L194-L195

Added lines #L194 - L195 were not covered by tests
}
} catch (RepositoryException e) {
LOG.error("Unable to get created date for package [ {} ]", jcrPackage.getNode().getPath(), e);
LOG.error("Unable to get created date for package [ {} ]", pkgDefinition.getNode().getPath(), e);

Check warning on line 198 in bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java

View check run for this annotation

Codecov / codecov/patch

bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java#L198

Added line #L198 was not covered by tests
return false;
}

LocalDate packageCreatedAt = LocalDateTime.ofInstant(
packageCreatedAtCalendar.toInstant(),
packageCreatedAtCalendar.getTimeZone().toZoneId()).toLocalDate();
String packageDescription = getPackageDescription(jcrPackage);
String packageDescription = getPackageDescription(pkgDefinition);

Check warning on line 205 in bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java

View check run for this annotation

Codecov / codecov/patch

bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java#L205

Added line #L205 was not covered by tests

if (LOG.isDebugEnabled()) {
LOG.debug("Checking if package is old enough: Name: {}, Created At: {}, Oldest Age: {}",
Expand All @@ -240,12 +211,7 @@
return !packageCreatedAt.isAfter(oldestAge);
}

private String getPackageDescription(JcrPackage jcrPackage) throws RepositoryException {
JcrPackageDefinition definition = jcrPackage.getDefinition();
Node packageNode = jcrPackage.getNode();
if (definition != null && packageNode != null) {
return String.format("%s:%s:v%s [%s]", definition.getId().getName(), definition.getId().getGroup(), definition.getId().getVersionString(), packageNode.getPath());
}
return "Unknown package";
private String getPackageDescription(JcrPackageDefinition definition) throws RepositoryException {
return String.format("%s:%s:v%s [%s]", definition.getId().getName(), definition.getId().getGroup(), definition.getId().getVersionString(), definition.getNode().getPath());

Check warning on line 215 in bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java

View check run for this annotation

Codecov / codecov/patch

bundle/src/main/java/com/adobe/acs/commons/packagegarbagecollector/PackageGarbageCollectionJob.java#L215

Added line #L215 was not covered by tests
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import org.apache.jackrabbit.vault.packaging.JcrPackageManager;
import org.apache.jackrabbit.vault.packaging.PackageId;
import org.apache.jackrabbit.vault.packaging.Packaging;
import org.apache.jackrabbit.vault.packaging.VaultPackage;
import org.apache.sling.event.jobs.Job;
import org.apache.sling.event.jobs.consumer.JobConsumer;
import org.apache.sling.testing.mock.sling.ResourceResolverType;
Expand Down Expand Up @@ -130,14 +129,12 @@ void mockPackageManager(JcrPackage... jcrPackage) throws RepositoryException {

JcrPackage mockPackage(Integer daysAgo, Integer lastUnpackedDaysAgo, String packageName, String name, String version) throws RepositoryException, IOException {
JcrPackage jcrPackage = mock(JcrPackage.class);
VaultPackage vaultPackage = mock(VaultPackage.class);
when(jcrPackage.getPackage()).thenReturn(vaultPackage);
when(vaultPackage.getCreated()).thenReturn(getDate(daysAgo));
Node packageNode = mock(Node.class);
when(packageNode.getPath()).thenReturn("/etc/packages/" + packageName);
when(jcrPackage.getNode()).thenReturn(packageNode);
JcrPackageDefinition definition = mock(JcrPackageDefinition.class);
when(definition.getLastUnpacked()).thenReturn(getDate(lastUnpackedDaysAgo));
when(definition.getCreated()).thenReturn(getDate(daysAgo));
when(definition.getNode()).thenReturn(packageNode);
PackageId pid = mock(PackageId.class);
when(pid.getName()).thenReturn(name);
when(pid.getGroup()).thenReturn("com.acs");
Expand Down
Loading