Skip to content

Instantly share code, notes, and snippets.

@abhishekanandttn
Created February 2, 2024 13:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save abhishekanandttn/e5584f20844acc1717648bfa6a9cc640 to your computer and use it in GitHub Desktop.
Save abhishekanandttn/e5584f20844acc1717648bfa6a9cc640 to your computer and use it in GitHub Desktop.
import com.day.cq.search.PredicateGroup;
import com.day.cq.search.Query;
import com.day.cq.search.QueryBuilder;
import com.day.cq.search.result.SearchResult;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.servlets.HttpConstants;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.LoggerFactory;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import java.io.IOException;
import java.util.*;
import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObjectBuilder;
import com.day.cq.dam.api.Asset;
//To generate report using the QueryBuilder API use: http://localhost:4502/content/projectName/us/en.assetsreport.csv?method=queryBuilder
//To generate report using the JCR API use: http://localhost:4502/content/projectName/us/en.assetsreport.csv?method=jcr
/**
* The type Assets report servlet.
*/
@Component(service = Servlet.class, property = {"sling.servlet.methods=" + HttpConstants.METHOD_GET,
"sling.servlet.resourceTypes=" + "sling/servlet/default", "sling.servlet.selectors=" + "assetsreport",
"sling.servlet.extensions=" + "csv"
})
public class AssetsReportServlet extends SlingAllMethodsServlet {
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(AssetsReportServlet.class);
private final String USER1 = "user1@gmail.com";
private final String USER2 = "user2@gmail.com";
@Reference
private QueryBuilder queryBuilder;
private static class AssetInfo {
private final String buName;
private final String assetName;
private final Calendar lastModified;
private final String lastModifiedBy;
/**
* Instantiates a new Asset info.
*
* @param buName the bu name
* @param assetName the asset name
* @param lastModified the last modified
* @param lastModifiedBy the last modified by
*/
public AssetInfo(String buName, String assetName, Calendar lastModified, String lastModifiedBy) {
this.buName = buName;
this.assetName = assetName;
this.lastModified = lastModified;
this.lastModifiedBy = lastModifiedBy;
}
/**
* Gets bu name.
*
* @return the bu name
*/
public String getBuName() {
return buName;
}
/**
* Gets asset name.
*
* @return the asset name
*/
public String getAssetName() {
return assetName;
}
/**
* Gets last modified.
*
* @return the last modified
*/
public Calendar getLastModified() {
return lastModified;
}
/**
* Gets last modified by.
*
* @return the last modified by
*/
public String getLastModifiedBy() {
return lastModifiedBy;
}
}
@Override
protected void doGet(final SlingHttpServletRequest req,
final SlingHttpServletResponse resp) throws ServletException, IOException {
try {
long startTimestamp = System.currentTimeMillis();
ResourceResolver resourceResolver = req.getResourceResolver();
if (resourceResolver == null) {
resp.getWriter().write("ResourceResolver is null");
return;
}
String requestType = req.getParameter("method");
Resource damResource = resourceResolver.getResource("/content/dam/");
if (damResource == null) {
resp.getWriter().write("DAM Resource is null");
return;
}
Map<String, AssetInfo> latestAssets = new HashMap<>();
if (requestType.equals("queryBuilder")) {
collectAssetNamesUsingQueryBuilder(damResource, resp, latestAssets);
} else {
if (requestType.equals("jcr")) {
collectAssetNamesUsingJcr(damResource, resp, "/", latestAssets);
} else {
resp.getWriter().write("invalid method type passed");
return;
}
}
JsonObjectBuilder jsonObjectBuilder = Json.createObjectBuilder();
JsonArrayBuilder jsonArrayBuilder = Json.createArrayBuilder();
List<Map.Entry<String, AssetInfo>> list = new ArrayList<>(latestAssets.entrySet());
list.sort((e1, e2) -> e2.getValue().getLastModified().compareTo(e1.getValue().getLastModified()));
Map<String, AssetInfo> sortedAssets = new LinkedHashMap<>();
for (Map.Entry<String, AssetInfo> entry : list) {
sortedAssets.put(entry.getKey(), entry.getValue());
}
for (AssetInfo asset : sortedAssets.values()) {
JsonObjectBuilder assetObjectBuilder = Json.createObjectBuilder();
assetObjectBuilder.add("BU name", asset.getBuName());
assetObjectBuilder.add("Asset name", asset.getAssetName());
assetObjectBuilder.add("Last modified", asset.getLastModified().getTime().toString());
assetObjectBuilder.add("Last modified by", asset.getLastModifiedBy()); // Include the new field
jsonArrayBuilder.add(assetObjectBuilder);
}
jsonObjectBuilder.add("assets", jsonArrayBuilder);
long endTimestamp = System.currentTimeMillis();
long processingTime = endTimestamp - startTimestamp;
LOGGER.error("Start Timestamp: {}", startTimestamp);
LOGGER.error("End Timestamp: {}", endTimestamp);
LOGGER.error("Processing Time (milliseconds): {}", processingTime);
StringBuilder csvContent = new StringBuilder();
csvContent.append("BU name,Asset name,Last modified,Last modified by\n");
for (AssetInfo asset : sortedAssets.values()) {
csvContent.append(String.format("%s,%s,%s,%s\n",
asset.getBuName(),
asset.getAssetName(),
asset.getLastModified().getTime(),
asset.getLastModifiedBy()));
}
resp.setContentType("text/csv");
resp.setCharacterEncoding("UTF-8");
resp.setHeader("Content-Disposition", "attachment; filename=assets_report.csv");
resp.getWriter().write(csvContent.toString());
resp.setContentType("application/json");
resp.setCharacterEncoding("UTF-8");
} catch (Exception e) {
resp.getWriter().write("An error occurred: " + e.getMessage());
}
}
private void collectAssetNamesUsingJcr(Resource resource, SlingHttpServletResponse resp, String pathPrefix, Map<String, AssetInfo> latestAssets) throws IOException, RepositoryException {
Iterator<Resource> assetIterator = resource.listChildren();
while (assetIterator.hasNext()) {
Resource assetResource = assetIterator.next();
if (assetResource == null) {
resp.getWriter().write("AssetResource is null");
return;
}
Asset asset = assetResource.adaptTo(Asset.class);
if (asset == null) {
collectAssetNamesUsingJcr(assetResource, resp, pathPrefix + assetResource.getName() + "/", latestAssets);
} else {
Node assetNode = asset.adaptTo(Node.class);
if (assetNode != null && assetNode.isNodeType("dam:Asset")) {
String nodeName = assetNode.getName();
String[] pathParts = pathPrefix.split("/");
String buName = pathParts[1];
Node contentNode = assetNode.getNode("jcr:content");
if (contentNode != null && contentNode.hasProperty("jcr:lastModified")) {
Calendar lastModified = contentNode.getProperty("jcr:lastModified").getDate();
String lastModifiedBy = getPropertyValue(contentNode, "jcr:lastModifiedBy");
if (!shouldSkipUser(lastModifiedBy)) {
AssetInfo currentLatestAsset = latestAssets.get(buName);
if (currentLatestAsset == null || lastModified.after(currentLatestAsset.getLastModified())) {
latestAssets.put(buName, new AssetInfo(buName, nodeName, lastModified, lastModifiedBy));
}
}
}
}
}
}
}
private void collectAssetNamesUsingQueryBuilder(Resource resource, SlingHttpServletResponse resp, Map<String, AssetInfo> latestAssets) throws IOException, RepositoryException {
try {
ResourceResolver resourceResolver = resource.getResourceResolver();
String queryString = "/content/dam";
Map<String, String> map = new HashMap<>();
map.put("path", queryString);
map.put("type", "dam:Asset");
map.put("p.limit", "-1");
Query query = queryBuilder.createQuery(PredicateGroup.create(map), resourceResolver.adaptTo(Session.class));
SearchResult result = query.getResult();
Map<String, AssetInfo> folderAssetMap = new HashMap<>();
Iterator<Node> nodes = result.getNodes();
while (nodes.hasNext()) {
Node assetNode = nodes.next();
String nodeName = assetNode.getName();
String[] parts = assetNode.getPath().split("/");
String parentFolderName = parts.length >= 4 ? parts[3] : "The string does not have a parent folder after '/content/dam/'";
if (assetNode.hasNode("jcr:content")) {
Node contentNode = assetNode.getNode("jcr:content");
if (contentNode.hasProperty("jcr:lastModified") && contentNode.hasProperty("jcr:lastModifiedBy")) {
Calendar lastModified = contentNode.getProperty("jcr:lastModified").getDate();
String lastModifiedBy = getPropertyValue(contentNode, "jcr:lastModifiedBy");
if (!shouldSkipUser(lastModifiedBy)) {
AssetInfo currentLatestAsset = folderAssetMap.get(parentFolderName);
if (currentLatestAsset == null || lastModified.after(currentLatestAsset.getLastModified())) {
folderAssetMap.put(parentFolderName, new AssetInfo(parentFolderName, nodeName, lastModified, lastModifiedBy));
}
}
}
}
}
latestAssets.putAll(folderAssetMap);
} catch (Exception e) {
resp.getWriter().write("An error occurred: " + e.getMessage());
}
}
private String getPropertyValue(Node node, String propertyName) throws RepositoryException {
if (node.hasProperty(propertyName)) {
Property property = node.getProperty(propertyName);
return property.getString();
}
return "";
}
private boolean shouldSkipUser(String lastModifiedBy) {
Set<String> usersToSkip = new HashSet<>(Arrays.asList(USER1, USER2));
return usersToSkip.contains(lastModifiedBy);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment