Skip to content

Commit

Permalink
Ccs 3993 sitemap (#497)
Browse files Browse the repository at this point in the history
* using sling resource fitler for sitemap
  • Loading branch information
xdavidson authored Jan 13, 2021
1 parent 39f2e58 commit eb586c7
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 0 deletions.
6 changes: 6 additions & 0 deletions pantheon-bundle/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,12 @@
<version>1.12.1</version>
</dependency>
<!-- Provided dependencies -->
<!-- https://mvnrepository.com/artifact/org.apache.sling/org.apache.sling.resource.filter -->
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.resource.filter</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,27 @@ public class PantheonConstants {
public static final String JCR_TYPE_ASSEMBLY = "pant:assembly";
public static final String JCR_TYPE_MODULEVARIANT = "pant:moduleVariant";
public static final String JCR_TYPE_ASSEMBLYVARIANT = "pant:assemblyVariant";
public static final String JCR_TYPE_MODULEVERSION = "pant:moduleVersion";
public static final String JCR_TYPE_ASSEMBLYVERSION = "pant:assemblyVersion";

public static final String LATEST_SUFFIX = "/latest";
public static final Set<String> RELEASED_SUFFIXES = new HashSet<>();

public static final String XML_DOCUMENT_VERSION = "1.0";
public static final String SITEMAP_NAMESPACE = "http://www.sitemaps.org/schemas/sitemap/0.9";
public static final String SITE_MAP = "sitemap";
public static final String SITEMAP_EXTENSION = "xml";
public static final String URL_SET = "urlset";
public static final String URL = "url";
public static final String LOC = "loc";
public static final String LAST_MOD = "lastmod";
public static final String UTF_8 = "utf-8";
public static final String XML_MIME_TYPE = "application/xml";

public static final String SLING_SERVLET_DEFAULT = "sling/servlet/default";
public static final String SLING_SERVLET_METHOD_GET = "GET";
public static final String VIEW_URI = "view_uri";
public static final String PORTAL_URL = "PORTAL_URL";
static {
RELEASED_SUFFIXES.add("/released");
RELEASED_SUFFIXES.add("/");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package com.redhat.pantheon.servlet.sitemap;

import com.redhat.pantheon.extension.url.CustomerPortalUrlUuidProvider;
import com.redhat.pantheon.extension.url.UrlProvider;
import com.redhat.pantheon.model.api.Child;
import com.redhat.pantheon.model.document.DocumentMetadata;
import com.redhat.pantheon.model.document.DocumentVariant;
import com.redhat.pantheon.model.document.DocumentVersion;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.resource.filter.ResourceFilterStream;
import org.apache.sling.servlets.annotations.SlingServletResourceTypes;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.Servlet;
import javax.servlet.http.HttpServletResponse;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

import static com.redhat.pantheon.helper.PantheonConstants.*;

@Component(
service = Servlet.class,
property = {
Constants.SERVICE_DESCRIPTION + "=Sitemap Servlet",
Constants.SERVICE_VENDOR + "=Red Hat Content Tooling team",
"sling.servlet.paths="+ "[\"/api/sitemap/module.sitemap.xml\", \"/api/sitemap/assembly.sitemap.xml\" ]"
}
)
@SlingServletResourceTypes(
resourceTypes = { SLING_SERVLET_DEFAULT },
methods = "GET",
extensions = SITEMAP_EXTENSION,
selectors = SITE_MAP)
public class SiteMapServlet extends SlingAllMethodsServlet {
private final Logger log = LoggerFactory.getLogger(SiteMapServlet.class);

private static final String RESOURCE_ROOT = "/content/repositories";

private Set<Resource> getAsset(Resource resource, String documentVersionResourceType) {

// Use Resource Filter Stream to limit memory consumption and path traversal
ResourceFilterStream rfs = resource.adaptTo(ResourceFilterStream.class);

return rfs.setChildSelector("[released/sling:resourceType] == '" + documentVersionResourceType + "'")
.stream()
.collect(Collectors.toSet());
}


@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
String documentVersionResourceType = "";
Resource resource = request.getResourceResolver().getResource(RESOURCE_ROOT);

if (request.getResource().getPath().startsWith("/api/sitemap/module.sitemap")) {
documentVersionResourceType = RESOURCE_TYPE_MODULEVERSION;
} else if (request.getResource().getPath().startsWith("/api/sitemap/assembly.sitemap")) {
documentVersionResourceType = RESOURCE_TYPE_ASSEMBLYVERSION;
} else {
log.warn("[" + SiteMapServlet.class.getSimpleName() + "] unhandled resource type: " + resource.getClass());
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}

Set<Resource> documentAssets = getAsset(resource, documentVersionResourceType);

if(documentAssets == null) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}

response.setContentType(XML_MIME_TYPE);
response.setCharacterEncoding(UTF_8);

XMLOutputFactory outputFactory = XMLOutputFactory.newFactory();
try {
XMLStreamWriter stream = outputFactory.createXMLStreamWriter(response.getWriter());

stream.writeStartDocument(XML_DOCUMENT_VERSION);
stream.writeStartElement("", URL_SET, SITEMAP_NAMESPACE);
stream.writeNamespace("", SITEMAP_NAMESPACE);

documentAssets.forEach(r -> {
try {
writeXML(r, stream, request);
} catch (XMLStreamException e) {
e.printStackTrace();
}
});

stream.writeEndElement();
stream.writeEndDocument();

} catch (XMLStreamException e) {
throw new IOException(e);
}
}

private void writeXML(Resource resource, XMLStreamWriter xmlStream, SlingHttpServletRequest slingRequest)
throws XMLStreamException {
xmlStream.writeStartElement(SITEMAP_NAMESPACE, URL);

String locPath = resource.getPath();
DocumentVariant documentVariant = null;
Date dateModified = null;

// Process external url
if (System.getenv(PORTAL_URL) != null) {
UrlProvider provider = new CustomerPortalUrlUuidProvider();
documentVariant = resource.adaptTo(DocumentVariant.class);

if (documentVariant != null && documentVariant.released().isPresent()) {
locPath = provider.generateUrlString(documentVariant);
}
} else {
locPath = resource.getPath();
}
writeXMLElement(xmlStream, LOC, locPath);
if (documentVariant != null) {
Optional<DocumentMetadata> releasedMetadata = (Optional<DocumentMetadata>) Child.from(documentVariant)
.toChild(DocumentVariant::released)
.toChild(DocumentVersion::metadata)
.asOptional();
dateModified = new Date(releasedMetadata.get().getValueMap().containsKey("pant:datePublished") ? releasedMetadata.get().datePublished().get().getTimeInMillis() : resource.getResourceMetadata().getModificationTime());
} else {
dateModified = new Date(resource.getResourceMetadata().getModificationTime());
}

if (dateModified != null) {
writeXMLElement(xmlStream, LAST_MOD, dateModified.toInstant().toString());
}

xmlStream.writeEndElement();
}

private void writeXMLElement(final XMLStreamWriter xmlStream, final String elementName, final String xmlText)
throws XMLStreamException {
xmlStream.writeStartElement(SITEMAP_NAMESPACE, elementName);
xmlStream.writeCharacters(xmlText);
xmlStream.writeEndElement();
}
}

0 comments on commit eb586c7

Please sign in to comment.