Author: ilgrosso
Date: Tue Apr 3 09:34:56 2012
New Revision: 1308780
URL: http://svn.apache.org/viewvc?rev=1308780&view=rev
Log:
[COCOON3-95] Applying and reworking a bit provided patch in order to handle sitemap XML validation when controller: and servlet: namespaces are also present; cocoon-sitemap-1.0.xsd further extended in order to deal with existing sitemap files
Modified:
cocoon/cocoon3/trunk/cocoon-sample/src/main/resources/COB-INF/sitemap.xmap
cocoon/cocoon3/trunk/cocoon-sitemap/src/main/java/org/apache/cocoon/sitemap/SitemapBuilder.java
cocoon/cocoon3/trunk/cocoon-sitemap/src/main/resources/cocoon-sitemap-1.0.xsd
Modified: cocoon/cocoon3/trunk/cocoon-sample/src/main/resources/COB-INF/sitemap.xmap
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-sample/src/main/resources/COB-INF/sitemap.xmap?rev=1308780&r1=1308779&r2=1308780&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-sample/src/main/resources/COB-INF/sitemap.xmap (original)
+++ cocoon/cocoon3/trunk/cocoon-sample/src/main/resources/COB-INF/sitemap.xmap Tue Apr 3 09:34:56 2012
@@ -19,7 +19,7 @@
-->
<!-- $Id$ -->
<map:sitemap xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:map="http://apache.org/cocoon/sitemap"
- xmlns:servlet="http://apache.org/cocoon/servlet" xmlns:controller="http://apache.org/cocoon/controller">
+ xmlns:servlet="http://apache.org/cocoon/servlet" xmlns:controller="http://apache.org/cocoon/controller">
<map:pipelines>
<!-- ~~~~~~~~~~~~~~~~ map:read ~~~~~~~~~~~~~~~ -->
@@ -45,7 +45,7 @@
<map:match pattern="read/style.css">
<map:read src="read/style.css"/>
</map:match>
- </map:pipeline>
+ </map:pipeline>
<!-- ~~~~~~~~~~~~~~~~ sax pipelines ~~~~~~~~~~~~~~~ -->
<map:pipeline jmx-group-name="sax">
@@ -386,13 +386,13 @@
<map:match equals="linkrewriting/regexplinkrewriter-transformer">
<map:generate src="linkrewriting/apache_home.html" />
<map:transform type="regexplinkrewriter">
- <map:parameter name="element1"
+ <map:parameter name="element1"
value="a href"/>
- <map:parameter name="element2"
+ <map:parameter name="element2"
value="http://www.w3.org/1999/xhtml link * href"/>
- <map:parameter name="regexp1"
+ <map:parameter name="regexp1"
value="^\./([\.]*) http://www.apache.org/$1"/>
- <map:parameter name="regexp2"
+ <map:parameter name="regexp2"
value="^/([\.]*) http://www.apache.org/$1"/>
</map:transform>
<map:serialize type="xml" />
@@ -557,16 +557,16 @@
<map:pipeline type="noncaching">
<map:match wildcard="string-template/generator">
<map:generate type="string-template" src="string-template/template.xml">
- <map:parameter name="parameter" value="A value"/>
- <map:parameter name="booleanParameter" value="{jexl:true}"/>
+ <map:parameter name="parameter" value="A value"/>
+ <map:parameter name="booleanParameter" value="{jexl:true}"/>
</map:generate>
<map:serialize/>
</map:match>
<map:match wildcard="string-template/transformer">
<map:generate src="string-template/template.xml"/>
<map:transform type="string-template">
- <map:parameter name="parameter" value="Another value"/>
- <map:parameter name="booleanParameter" value="{jexl:false}"/>
+ <map:parameter name="parameter" value="Another value"/>
+ <map:parameter name="booleanParameter" value="{jexl:false}"/>
</map:transform>
<map:serialize/>
</map:match>
Modified: cocoon/cocoon3/trunk/cocoon-sitemap/src/main/java/org/apache/cocoon/sitemap/SitemapBuilder.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-sitemap/src/main/java/org/apache/cocoon/sitemap/SitemapBuilder.java?rev=1308780&r1=1308779&r2=1308780&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-sitemap/src/main/java/org/apache/cocoon/sitemap/SitemapBuilder.java (original)
+++ cocoon/cocoon3/trunk/cocoon-sitemap/src/main/java/org/apache/cocoon/sitemap/SitemapBuilder.java Tue Apr 3 09:34:56 2012
@@ -18,14 +18,21 @@
*/
package org.apache.cocoon.sitemap;
+import java.io.File;
import java.io.InputStream;
+import java.net.URISyntaxException;
import java.net.URL;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
-
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
-
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.SchemaFactory;
+import org.apache.cocoon.sax.util.InMemoryLRUResourceCache;
+import org.apache.cocoon.sax.util.ValidityValue;
import org.apache.cocoon.sitemap.node.SitemapNode;
import org.apache.cocoon.sitemap.node.SitemapNodeFactory;
import org.xml.sax.Attributes;
@@ -35,31 +42,88 @@ import org.xml.sax.helpers.DefaultHandle
public class SitemapBuilder {
+ /**
+ * Store sitemap file validity.
+ */
+ private static final InMemoryLRUResourceCache<URL> URL_LRU_CACHE = new InMemoryLRUResourceCache<URL>();
+
private SitemapNodeFactory sitemapNodeFactory;
public SitemapNode build(URL sitemap) {
if (sitemap == null) {
- throw new NullPointerException("A valid sitemap URL has to be passed.");
+ throw new IllegalArgumentException("Null sitemap URL was passed");
}
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
saxParserFactory.setNamespaceAware(true);
- // saxParserFactory.setSchema(SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema").newSchema());
+ enableValidation(sitemap, saxParserFactory);
- SitemapHandler sitemapHandler = new SitemapHandler();
+ final SitemapHandler sitemapHandler = new SitemapHandler();
try {
- SAXParser saxParser = saxParserFactory.newSAXParser();
+ final SAXParser saxParser = saxParserFactory.newSAXParser();
- InputStream inputStream = sitemap.openStream();
+ final InputStream inputStream = sitemap.openStream();
saxParser.parse(inputStream, sitemapHandler);
inputStream.close();
} catch (Exception e) {
- throw new SitemapBuilderException("Can't build sitemap.", e);
+ URL_LRU_CACHE.put(sitemap.toExternalForm(), new ValidityValue<URL>(sitemap, -1));
+ throw new SitemapBuilderException("Can't build sitemap from " + sitemap.toExternalForm(), e);
}
return sitemapHandler.getSitemap();
}
+ /**
+ * Enable sitemap validation against the XSD schema.
+ *
+ * Use {@link InMemoryLRUResourceCache} to validate once until sitemap file changes.
+ *
+ * @param sitemap An {@link URL} with sitemap location.
+ * @param saxParserFactory {@link SAXParserFactory} to configure the schema.
+ */
+ protected void enableValidation(final URL sitemap, final SAXParserFactory saxParserFactory) {
+ if ("file".equals(sitemap.getProtocol())) {
+ File sitemapFile;
+ try {
+ sitemapFile = new File(sitemap.toURI());
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException("Invalid source specified: " + sitemap, e);
+ }
+
+ if (URL_LRU_CACHE.containsKey(sitemap.toExternalForm())
+ && URL_LRU_CACHE.get(sitemap.toExternalForm()).getLastModified() >= sitemapFile.lastModified()) {
+
+ return;
+ }
+
+ final ValidityValue<URL> validity = new ValidityValue<URL>(sitemap, sitemapFile.lastModified());
+ URL_LRU_CACHE.put(sitemap.toExternalForm(), validity);
+ }
+
+ final List<Source> xsdSources = new ArrayList<Source>();
+
+ // This XSD is mandatory
+ final InputStream sitemapSchema = this.getClass().getResourceAsStream("/cocoon-sitemap-1.0.xsd");
+ xsdSources.add(new StreamSource(sitemapSchema));
+
+ // These two might be present in classpath or not: if present, they will be included for validation
+ final InputStream servletSchema = this.getClass().getResourceAsStream("/cocoon-servlet-1.0.xsd");
+ if (servletSchema != null) {
+ xsdSources.add(new StreamSource(servletSchema));
+ }
+ final InputStream controllerSchema = this.getClass().getResourceAsStream("/cocoon-controller-1.0.xsd");
+ if (controllerSchema != null) {
+ xsdSources.add(new StreamSource(controllerSchema));
+ }
+
+ try {
+ saxParserFactory.setSchema(SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema").
+ newSchema(xsdSources.toArray(new Source[xsdSources.size()])));
+ } catch (SAXException e) {
+ throw new SitemapBuilderException("Unable to load the sitemap", e);
+ }
+ }
+
public void setSitemapNodeFactory(SitemapNodeFactory sitemapNodeFactory) {
this.sitemapNodeFactory = sitemapNodeFactory;
}
@@ -80,6 +144,7 @@ public class SitemapBuilder {
private class SitemapHandler extends DefaultHandler {
private SitemapNode currentNode;
+
private SitemapNode sitemap;
@Override
Modified: cocoon/cocoon3/trunk/cocoon-sitemap/src/main/resources/cocoon-sitemap-1.0.xsd
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-sitemap/src/main/resources/cocoon-sitemap-1.0.xsd?rev=1308780&r1=1308779&r2=1308780&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-sitemap/src/main/resources/cocoon-sitemap-1.0.xsd (original)
+++ cocoon/cocoon3/trunk/cocoon-sitemap/src/main/resources/cocoon-sitemap-1.0.xsd Tue Apr 3 09:34:56 2012
@@ -17,8 +17,8 @@
-->
<!-- $Id$ -->
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://apache.org/cocoon/sitemap"
- xmlns:tns="http://apache.org/cocoon/sitemap" xmlns="http://apache.org/cocoon/sitemap"
- elementFormDefault="qualified">
+ xmlns:tns="http://apache.org/cocoon/sitemap" xmlns="http://apache.org/cocoon/sitemap"
+ elementFormDefault="qualified">
<xsd:annotation>
<xsd:documentation>Schema for the Cocoon 3 sitemap language.</xsd:documentation>
@@ -76,6 +76,20 @@
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
+ <xsd:attribute name="expires" type="xsd:integer" use="optional">
+ <xsd:annotation>
+ <xsd:documentation>
+ Expires time in seconds.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="expires-cache-key" type="xsd:string" use="optional">
+ <xsd:annotation>
+ <xsd:documentation>
+ Expires pipelines that have non-cacheable pipeline components require an explicit cache key.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
</xsd:complexType>
</xsd:element>
@@ -130,6 +144,11 @@
</xsd:annotation>
</xsd:attribute>
<xsd:attributeGroup ref="expression-attrs" />
+ <xsd:attribute name="name" type="xsd:string" use="optional">
+ <xsd:annotation>
+ <xsd:documentation>Attribute for referencing named matchers.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
</xsd:complexType>
</xsd:element>
@@ -241,6 +260,11 @@
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
+ <xsd:attribute name="id" type="xsd:string" use="optional">
+ <xsd:annotation>
+ <xsd:documentation>Id of this generator (for profiling).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
</xsd:complexType>
</xsd:element>
@@ -291,6 +315,31 @@
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
+ <xsd:attribute name="id" type="xsd:string" use="optional">
+ <xsd:annotation>
+ <xsd:documentation>Id of this serializer (for profiling).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="indent" type="xsd:integer" use="optional">
+ <xsd:annotation>
+ <xsd:documentation>Number of spaces per each indentation step.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="doctype-default" type="xsd:string" use="optional">
+ <xsd:annotation>
+ <xsd:documentation>Doctype (for encoding serializers).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="omitXmlDeclaration" type="xsd:string" use="optional">
+ <xsd:annotation>
+ <xsd:documentation>Whether to omit XML declaration.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="encoding" type="xsd:string" use="optional">
+ <xsd:annotation>
+ <xsd:documentation>Encoding for serialization (for encoding serializers).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
</xsd:complexType>
</xsd:element>
@@ -325,6 +374,11 @@
<xsd:documentation>The mime-type of the pipeline result.</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
+ <xsd:attribute name="base-path" type="xsd:string" use="optional">
+ <xsd:annotation>
+ <xsd:documentation>Base path (for usage with Wicket reader).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
</xsd:complexType>
</xsd:element>
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.