Skip to content

Commit eb586c7

Browse files
authored
Ccs 3993 sitemap (#497)
* using sling resource fitler for sitemap
1 parent 39f2e58 commit eb586c7

File tree

3 files changed

+176
-0
lines changed

3 files changed

+176
-0
lines changed

pantheon-bundle/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,12 @@
313313
<version>1.12.1</version>
314314
</dependency>
315315
<!-- Provided dependencies -->
316+
<!-- https://mvnrepository.com/artifact/org.apache.sling/org.apache.sling.resource.filter -->
317+
<dependency>
318+
<groupId>org.apache.sling</groupId>
319+
<artifactId>org.apache.sling.resource.filter</artifactId>
320+
<version>1.0.0</version>
321+
</dependency>
316322
<dependency>
317323
<groupId>javax.servlet</groupId>
318324
<artifactId>javax.servlet-api</artifactId>

pantheon-bundle/src/main/java/com/redhat/pantheon/helper/PantheonConstants.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,27 @@ public class PantheonConstants {
2121
public static final String JCR_TYPE_ASSEMBLY = "pant:assembly";
2222
public static final String JCR_TYPE_MODULEVARIANT = "pant:moduleVariant";
2323
public static final String JCR_TYPE_ASSEMBLYVARIANT = "pant:assemblyVariant";
24+
public static final String JCR_TYPE_MODULEVERSION = "pant:moduleVersion";
25+
public static final String JCR_TYPE_ASSEMBLYVERSION = "pant:assemblyVersion";
2426

2527
public static final String LATEST_SUFFIX = "/latest";
2628
public static final Set<String> RELEASED_SUFFIXES = new HashSet<>();
29+
30+
public static final String XML_DOCUMENT_VERSION = "1.0";
31+
public static final String SITEMAP_NAMESPACE = "http://www.sitemaps.org/schemas/sitemap/0.9";
32+
public static final String SITE_MAP = "sitemap";
33+
public static final String SITEMAP_EXTENSION = "xml";
34+
public static final String URL_SET = "urlset";
35+
public static final String URL = "url";
36+
public static final String LOC = "loc";
37+
public static final String LAST_MOD = "lastmod";
38+
public static final String UTF_8 = "utf-8";
39+
public static final String XML_MIME_TYPE = "application/xml";
40+
41+
public static final String SLING_SERVLET_DEFAULT = "sling/servlet/default";
42+
public static final String SLING_SERVLET_METHOD_GET = "GET";
43+
public static final String VIEW_URI = "view_uri";
44+
public static final String PORTAL_URL = "PORTAL_URL";
2745
static {
2846
RELEASED_SUFFIXES.add("/released");
2947
RELEASED_SUFFIXES.add("/");
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
package com.redhat.pantheon.servlet.sitemap;
2+
3+
import com.redhat.pantheon.extension.url.CustomerPortalUrlUuidProvider;
4+
import com.redhat.pantheon.extension.url.UrlProvider;
5+
import com.redhat.pantheon.model.api.Child;
6+
import com.redhat.pantheon.model.document.DocumentMetadata;
7+
import com.redhat.pantheon.model.document.DocumentVariant;
8+
import com.redhat.pantheon.model.document.DocumentVersion;
9+
import org.apache.sling.api.SlingHttpServletRequest;
10+
import org.apache.sling.api.SlingHttpServletResponse;
11+
import org.apache.sling.api.resource.Resource;
12+
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
13+
import org.apache.sling.resource.filter.ResourceFilterStream;
14+
import org.apache.sling.servlets.annotations.SlingServletResourceTypes;
15+
import org.osgi.framework.Constants;
16+
import org.osgi.service.component.annotations.Component;
17+
import org.slf4j.Logger;
18+
import org.slf4j.LoggerFactory;
19+
20+
import javax.servlet.Servlet;
21+
import javax.servlet.http.HttpServletResponse;
22+
import javax.xml.stream.XMLOutputFactory;
23+
import javax.xml.stream.XMLStreamException;
24+
import javax.xml.stream.XMLStreamWriter;
25+
import java.io.IOException;
26+
import java.util.*;
27+
import java.util.stream.Collectors;
28+
29+
import static com.redhat.pantheon.helper.PantheonConstants.*;
30+
31+
@Component(
32+
service = Servlet.class,
33+
property = {
34+
Constants.SERVICE_DESCRIPTION + "=Sitemap Servlet",
35+
Constants.SERVICE_VENDOR + "=Red Hat Content Tooling team",
36+
"sling.servlet.paths="+ "[\"/api/sitemap/module.sitemap.xml\", \"/api/sitemap/assembly.sitemap.xml\" ]"
37+
}
38+
)
39+
@SlingServletResourceTypes(
40+
resourceTypes = { SLING_SERVLET_DEFAULT },
41+
methods = "GET",
42+
extensions = SITEMAP_EXTENSION,
43+
selectors = SITE_MAP)
44+
public class SiteMapServlet extends SlingAllMethodsServlet {
45+
private final Logger log = LoggerFactory.getLogger(SiteMapServlet.class);
46+
47+
private static final String RESOURCE_ROOT = "/content/repositories";
48+
49+
private Set<Resource> getAsset(Resource resource, String documentVersionResourceType) {
50+
51+
// Use Resource Filter Stream to limit memory consumption and path traversal
52+
ResourceFilterStream rfs = resource.adaptTo(ResourceFilterStream.class);
53+
54+
return rfs.setChildSelector("[released/sling:resourceType] == '" + documentVersionResourceType + "'")
55+
.stream()
56+
.collect(Collectors.toSet());
57+
}
58+
59+
60+
@Override
61+
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
62+
String documentVersionResourceType = "";
63+
Resource resource = request.getResourceResolver().getResource(RESOURCE_ROOT);
64+
65+
if (request.getResource().getPath().startsWith("/api/sitemap/module.sitemap")) {
66+
documentVersionResourceType = RESOURCE_TYPE_MODULEVERSION;
67+
} else if (request.getResource().getPath().startsWith("/api/sitemap/assembly.sitemap")) {
68+
documentVersionResourceType = RESOURCE_TYPE_ASSEMBLYVERSION;
69+
} else {
70+
log.warn("[" + SiteMapServlet.class.getSimpleName() + "] unhandled resource type: " + resource.getClass());
71+
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
72+
return;
73+
}
74+
75+
Set<Resource> documentAssets = getAsset(resource, documentVersionResourceType);
76+
77+
if(documentAssets == null) {
78+
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
79+
return;
80+
}
81+
82+
response.setContentType(XML_MIME_TYPE);
83+
response.setCharacterEncoding(UTF_8);
84+
85+
XMLOutputFactory outputFactory = XMLOutputFactory.newFactory();
86+
try {
87+
XMLStreamWriter stream = outputFactory.createXMLStreamWriter(response.getWriter());
88+
89+
stream.writeStartDocument(XML_DOCUMENT_VERSION);
90+
stream.writeStartElement("", URL_SET, SITEMAP_NAMESPACE);
91+
stream.writeNamespace("", SITEMAP_NAMESPACE);
92+
93+
documentAssets.forEach(r -> {
94+
try {
95+
writeXML(r, stream, request);
96+
} catch (XMLStreamException e) {
97+
e.printStackTrace();
98+
}
99+
});
100+
101+
stream.writeEndElement();
102+
stream.writeEndDocument();
103+
104+
} catch (XMLStreamException e) {
105+
throw new IOException(e);
106+
}
107+
}
108+
109+
private void writeXML(Resource resource, XMLStreamWriter xmlStream, SlingHttpServletRequest slingRequest)
110+
throws XMLStreamException {
111+
xmlStream.writeStartElement(SITEMAP_NAMESPACE, URL);
112+
113+
String locPath = resource.getPath();
114+
DocumentVariant documentVariant = null;
115+
Date dateModified = null;
116+
117+
// Process external url
118+
if (System.getenv(PORTAL_URL) != null) {
119+
UrlProvider provider = new CustomerPortalUrlUuidProvider();
120+
documentVariant = resource.adaptTo(DocumentVariant.class);
121+
122+
if (documentVariant != null && documentVariant.released().isPresent()) {
123+
locPath = provider.generateUrlString(documentVariant);
124+
}
125+
} else {
126+
locPath = resource.getPath();
127+
}
128+
writeXMLElement(xmlStream, LOC, locPath);
129+
if (documentVariant != null) {
130+
Optional<DocumentMetadata> releasedMetadata = (Optional<DocumentMetadata>) Child.from(documentVariant)
131+
.toChild(DocumentVariant::released)
132+
.toChild(DocumentVersion::metadata)
133+
.asOptional();
134+
dateModified = new Date(releasedMetadata.get().getValueMap().containsKey("pant:datePublished") ? releasedMetadata.get().datePublished().get().getTimeInMillis() : resource.getResourceMetadata().getModificationTime());
135+
} else {
136+
dateModified = new Date(resource.getResourceMetadata().getModificationTime());
137+
}
138+
139+
if (dateModified != null) {
140+
writeXMLElement(xmlStream, LAST_MOD, dateModified.toInstant().toString());
141+
}
142+
143+
xmlStream.writeEndElement();
144+
}
145+
146+
private void writeXMLElement(final XMLStreamWriter xmlStream, final String elementName, final String xmlText)
147+
throws XMLStreamException {
148+
xmlStream.writeStartElement(SITEMAP_NAMESPACE, elementName);
149+
xmlStream.writeCharacters(xmlText);
150+
xmlStream.writeEndElement();
151+
}
152+
}

0 commit comments

Comments
 (0)