You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2008/11/28 13:29:49 UTC

svn commit: r721453 - in /incubator/sling/trunk: ./ samples/espblog/ samples/espblog/src/ samples/espblog/src/main/ samples/espblog/src/main/java/ samples/espblog/src/main/java/org/ samples/espblog/src/main/java/org/apache/ samples/espblog/src/main/jav...

Author: bdelacretaz
Date: Fri Nov 28 04:29:48 2008
New Revision: 721453

URL: http://svn.apache.org/viewvc?rev=721453&view=rev
Log:
SLING-673, ESP-based blog sample, based on a contribution by Michael Marth, thanks!

Added:
    incubator/sling/trunk/samples/espblog/   (with props)
    incubator/sling/trunk/samples/espblog/README.txt   (with props)
    incubator/sling/trunk/samples/espblog/pom.xml   (with props)
    incubator/sling/trunk/samples/espblog/src/
    incubator/sling/trunk/samples/espblog/src/main/
    incubator/sling/trunk/samples/espblog/src/main/java/
    incubator/sling/trunk/samples/espblog/src/main/java/org/
    incubator/sling/trunk/samples/espblog/src/main/java/org/apache/
    incubator/sling/trunk/samples/espblog/src/main/java/org/apache/sling/
    incubator/sling/trunk/samples/espblog/src/main/java/org/apache/sling/samples/
    incubator/sling/trunk/samples/espblog/src/main/java/org/apache/sling/samples/espblog/
    incubator/sling/trunk/samples/espblog/src/main/java/org/apache/sling/samples/espblog/ThumbnailGeneratorService.java   (with props)
    incubator/sling/trunk/samples/espblog/src/main/java/org/apache/sling/samples/espblog/internal/
    incubator/sling/trunk/samples/espblog/src/main/java/org/apache/sling/samples/espblog/internal/ThumbnailGeneratorServiceImpl.java   (with props)
    incubator/sling/trunk/samples/espblog/src/main/resources/
    incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/
    incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/
    incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/
    incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/admin.esp
    incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/constants.esp
    incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/edit.esp
    incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/espblog.css   (with props)
    incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/header.esp
    incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/html.esp
    incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/list.esp
    incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/menu.esp
    incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/sling-logo.png   (with props)
    incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/xml.esp
Modified:
    incubator/sling/trunk/pom.xml

Modified: incubator/sling/trunk/pom.xml
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/pom.xml?rev=721453&r1=721452&r2=721453&view=diff
==============================================================================
--- incubator/sling/trunk/pom.xml (original)
+++ incubator/sling/trunk/pom.xml Fri Nov 28 04:29:48 2008
@@ -121,6 +121,7 @@
         <module>samples/path-based-rtp</module>
         <module>samples/webloader/service</module>
         <module>samples/webloader/ui</module>
+        <module>samples/espblog</module>
 
         <!-- Launchpad -->
         <module>launchpad/base</module>

Propchange: incubator/sling/trunk/samples/espblog/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Fri Nov 28 04:29:48 2008
@@ -0,0 +1,11 @@
+target
+bin
+*.iml
+*.ipr
+*.iws
+.settings
+.project
+.classpath
+.externalToolBuilders
+maven-eclipse.xml
+

Added: incubator/sling/trunk/samples/espblog/README.txt
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/samples/espblog/README.txt?rev=721453&view=auto
==============================================================================
--- incubator/sling/trunk/samples/espblog/README.txt (added)
+++ incubator/sling/trunk/samples/espblog/README.txt Fri Nov 28 04:29:48 2008
@@ -0,0 +1,46 @@
+Sling ESP blog sample
+---------------------
+
+WHY THIS SAMPLE?
+----------------
+This demonstrates the use of ESP server-side javascript to implement a simple
+blog, with file attachments.
+
+A java service uses JCR observation to detect incoming files (either uploaded
+via the blog forms, or copied via WebDAV), and creates thumbnails of files image
+files, to demonstrate observation and OSGi SCR services.
+
+HOW TO INSTALL
+--------------
+Build this bundle and install it in Sling.
+
+For example, if Sling is running on port 8888 (which happens if you start 
+the launchpad/testing module with "mvn jetty:run"), this will build and 
+install it:
+
+    mvn -P autoInstallBundle clean install -Dsling.url=http://localhost:8888/system/console
+    
+To verify that the bundle is correctly installed:
+
+1) http://localhost:8888/apps/espblog/html.esp must return the html.esp 
+   script.
+
+2) The console at http://localhost:8888/system/console/bundles must 
+    list the bundle named "Sling - ESP blog sample" as active.    
+
+You also need to set "allow anonymous access" to false in the 
+SlingAuthenticator config, via http://localhost:8888/system/console/configMgr
+
+HOW TO TEST
+-----------
+http://localhost:8888/content/espblog/*.html must display the "Sling ESP
+blog sample" page, with the Home/Admin/New Post/... menu.
+
+Create a new post using the "New Post" menu.
+
+The post can include an attachment, if that's an image the included
+ThumbnailGeneratorService generates thumbnails in different sizes, displayed
+on the post's page. This happens asynchronously, so depending on your 
+machine's speed the thumbnails might only appear after a few seconds.
+
+The ESP scripts are found under /apps/espblog in the repository.
\ No newline at end of file

Propchange: incubator/sling/trunk/samples/espblog/README.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sling/trunk/samples/espblog/pom.xml
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/samples/espblog/pom.xml?rev=721453&view=auto
==============================================================================
--- incubator/sling/trunk/samples/espblog/pom.xml (added)
+++ incubator/sling/trunk/samples/espblog/pom.xml Fri Nov 28 04:29:48 2008
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+  <!--
+    Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for
+    additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not
+    use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
+    applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  
+  <parent>
+    <groupId>org.apache.sling</groupId>
+    <artifactId>sling</artifactId>
+    <version>3-incubator</version>
+    <relativePath>../../../parent/pom.xml</relativePath>
+  </parent>
+   
+  <groupId>org.apache.sling.samples</groupId>
+  <artifactId>org.apache.sling.samples.espblog</artifactId>
+  <packaging>bundle</packaging>
+  <version>2.0.3-incubator-SNAPSHOT</version>
+  <name>Sling - ESP blog sample</name>
+  <description>
+    Sample Sling application - blog written using ESP scripts.
+  </description>
+  
+  <scm>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/incubator/sling/trunk/samples/espblog</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/incubator/sling/trunk/samples/espblog</developerConnection>
+    <url>http://svn.apache.org/viewvc/incubator/sling/trunk/samples/espblog</url>
+  </scm>
+  
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-scr-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Sling-Initial-Content>initial-content</Sling-Initial-Content>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  
+  <reporting>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <configuration>
+          <excludePackageNames>org.apache.sling.samples.espblog.internal</excludePackageNames>
+        </configuration>
+      </plugin>
+    </plugins>
+  </reporting>
+  
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.api</artifactId>
+      <version>2.0.2-incubator</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.jcr.api</artifactId>
+      <version>2.0.2-incubator</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+  
+</project>
\ No newline at end of file

Propchange: incubator/sling/trunk/samples/espblog/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sling/trunk/samples/espblog/src/main/java/org/apache/sling/samples/espblog/ThumbnailGeneratorService.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/samples/espblog/src/main/java/org/apache/sling/samples/espblog/ThumbnailGeneratorService.java?rev=721453&view=auto
==============================================================================
--- incubator/sling/trunk/samples/espblog/src/main/java/org/apache/sling/samples/espblog/ThumbnailGeneratorService.java (added)
+++ incubator/sling/trunk/samples/espblog/src/main/java/org/apache/sling/samples/espblog/ThumbnailGeneratorService.java Fri Nov 28 04:29:48 2008
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.samples.espblog;
+
+/** Empty interface, the SCR plugin requires one
+ *  to process our service implementation.
+ */
+public interface ThumbnailGeneratorService {
+}
\ No newline at end of file

Propchange: incubator/sling/trunk/samples/espblog/src/main/java/org/apache/sling/samples/espblog/ThumbnailGeneratorService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/sling/trunk/samples/espblog/src/main/java/org/apache/sling/samples/espblog/ThumbnailGeneratorService.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: incubator/sling/trunk/samples/espblog/src/main/java/org/apache/sling/samples/espblog/internal/ThumbnailGeneratorServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/samples/espblog/src/main/java/org/apache/sling/samples/espblog/internal/ThumbnailGeneratorServiceImpl.java?rev=721453&view=auto
==============================================================================
--- incubator/sling/trunk/samples/espblog/src/main/java/org/apache/sling/samples/espblog/internal/ThumbnailGeneratorServiceImpl.java (added)
+++ incubator/sling/trunk/samples/espblog/src/main/java/org/apache/sling/samples/espblog/internal/ThumbnailGeneratorServiceImpl.java Fri Nov 28 04:29:48 2008
@@ -0,0 +1,214 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.samples.espblog.internal;
+
+import java.awt.Graphics2D;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.imageio.ImageIO;
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.EventListener;
+import javax.jcr.observation.ObservationManager;
+
+import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.samples.espblog.ThumbnailGeneratorService;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Observe the espblog content for changes, and generate
+ * thumbnails when images are added.
+ * 
+ * @scr.service
+ * @scr.component immediate="true" metatype="false"
+ * @scr.property name="service.description" value="Sling ESP blog sample thumbnails generator"
+ * @scr.property name="service.vendor" value="Apache Software Foundation"
+ * 
+ */
+public class ThumbnailGeneratorServiceImpl implements ThumbnailGeneratorService, EventListener {
+
+    private Session session;
+    private ObservationManager observationManager;
+    
+	/** @scr.reference */
+	private SlingRepository repository;
+	
+    /** @scr.property value="/content/espblog" */
+    private static final String CONTENT_PATH_PROPERTY = "content.path";
+
+	private static final Logger log = LoggerFactory
+			.getLogger(ThumbnailGeneratorServiceImpl.class);
+	
+	private Map<String, String> supportedMimeTypes = new HashMap<String, String>();
+
+	protected void activate(ComponentContext context)  throws Exception {
+	    supportedMimeTypes.put("image/jpeg", ".jpg");
+        supportedMimeTypes.put("image/png", ".png");
+        
+        String contentPath = (String)context.getProperties().get(CONTENT_PATH_PROPERTY);
+
+		session = repository.loginAdministrative(null);
+		if (repository.getDescriptor(Repository.OPTION_OBSERVATION_SUPPORTED).equals("true")) {
+			observationManager = session.getWorkspace().getObservationManager();
+			String[] types = { "nt:file" };
+			observationManager.addEventListener(this, Event.NODE_ADDED, contentPath, true, null, types, false);
+		}
+	}
+	
+    protected void deactivate(ComponentContext componentContext) throws RepositoryException {
+        if(observationManager != null) {
+            observationManager.removeEventListener(this);
+        }
+        if (session != null) {
+            session.logout();
+            session = null;
+        }
+    }
+
+	public void onEvent(EventIterator it) {
+        while (it.hasNext()) {
+            Event event = it.nextEvent();
+            try {
+                if (event.getType() == Event.NODE_ADDED && !(event.getPath().contains("thumbnails"))) {
+                    log.info("new upload: {}", event.getPath());
+                    Node addedNode = session.getRootNode().getNode(event.getPath().substring(1));
+                    processNewNode(addedNode);
+                    log.info("finished processing of {}", event.getPath());
+                }
+            } catch (Exception e) {
+                log.error(e.getMessage(), e);
+            }
+        }
+    }
+
+    private String getMimeType(Node n) throws RepositoryException {
+	    String result = null;
+		final String mimeType = n.getProperty("jcr:mimeType").getString();
+		
+		for(String key : supportedMimeTypes.keySet()) {
+		    if(mimeType!=null && mimeType.startsWith(key)) {
+		        result = key;
+		        break;
+		    }
+		}
+		
+		if(result == null) {
+			log.info("Node {} rejected, unsupported mime-type {}", n.getPath(), mimeType);
+		}
+		
+		if(n.getName().startsWith(".")) {
+			log.info("Node {} rejected, name starts with '.'", n.getPath(), mimeType);
+			result = null;
+		}
+		
+		return result;
+	}
+	
+	private void processNewNode(Node addedNode) throws Exception {
+	    final String mimeType = getMimeType(addedNode);
+		if (mimeType == null) {
+			return;
+		}
+		final String suffix = supportedMimeTypes.get(mimeType); 
+		
+		// Scale to a temp file for simplicity
+		log.info("Creating thumbnails for node {}", addedNode.getPath());
+		final int [] widths = { 50, 100, 250 };
+		for(int width : widths) {
+		    createThumbnail(addedNode, width, mimeType, suffix);
+		}
+	}
+	
+	private void createThumbnail(Node image, int scalePercent, String mimeType, String suffix) throws Exception {
+        final File tmp = File.createTempFile(getClass().getSimpleName(), suffix);
+        try {
+            scale(image.getProperty("jcr:data").getStream(), scalePercent, new FileOutputStream(tmp), suffix);
+            
+            // Create thumbnail node and set the mandatory properties
+            Node thumbnailFolder = getThumbnailFolder(image);
+            Node thumbnail = thumbnailFolder.addNode(image.getParent().getName() + "_" + scalePercent + suffix, "nt:file");
+            Node contentNode = thumbnail.addNode("jcr:content", "nt:resource");
+            contentNode.setProperty("jcr:data", new FileInputStream(tmp));
+            contentNode.setProperty("jcr:lastModified", Calendar.getInstance());    
+            contentNode.setProperty("jcr:mimeType", mimeType);
+
+            session.save();
+            
+            log.info("Created thumbnail " + contentNode.getPath());
+        } finally {
+            if(tmp != null) {
+                tmp.delete();
+            }
+        }
+	    
+	}
+
+	private Node getThumbnailFolder(Node addedNode) throws Exception {
+		Node post = addedNode.getParent().getParent().getParent();
+		if (post.hasNode("thumbnails")) {
+			log.info("thumbnails node exists already at " + post.getPath());
+			return post.getNode("thumbnails");
+		} else {
+			Node t = post.addNode("thumbnails", "nt:folder");
+			session.save();
+			return t;
+		}
+	}
+
+	public void scale(InputStream inputStream, int width, OutputStream outputStream, String suffix) throws IOException {
+		if(inputStream == null) {
+			throw new IOException("InputStream is null");
+		}
+		
+        final BufferedImage src = ImageIO.read(inputStream);
+		if(src == null) {
+		    final StringBuffer sb = new StringBuffer();
+		    for(String fmt : ImageIO.getReaderFormatNames()) {
+		        sb.append(fmt);
+		        sb.append(' ');
+		    }
+			throw new IOException("Unable to read image, registered formats: " + sb);
+		}
+		
+        final double scale = (double)width / src.getWidth();
+        
+		int destWidth = width;
+		int destHeight = new Double(src.getHeight() * scale).intValue();
+		log.debug("Generating thumbnail, w={}, h={}", destWidth, destHeight);
+		BufferedImage dest = new BufferedImage(destWidth, destHeight, BufferedImage.TYPE_INT_RGB);
+		Graphics2D g = dest.createGraphics();
+		AffineTransform at = AffineTransform.getScaleInstance((double) destWidth / src.getWidth(), (double) destHeight	/ src.getHeight());
+		g.drawRenderedImage(src, at);
+		ImageIO.write(dest, suffix.substring(1), outputStream);
+	}
+}
\ No newline at end of file

Propchange: incubator/sling/trunk/samples/espblog/src/main/java/org/apache/sling/samples/espblog/internal/ThumbnailGeneratorServiceImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/sling/trunk/samples/espblog/src/main/java/org/apache/sling/samples/espblog/internal/ThumbnailGeneratorServiceImpl.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/admin.esp
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/admin.esp?rev=721453&view=auto
==============================================================================
--- incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/admin.esp (added)
+++ incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/admin.esp Fri Nov 28 04:29:48 2008
@@ -0,0 +1,82 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+
+<% 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+%>
+ 
+<html>
+<%
+pageTitle = "Blog admin"
+load("header.esp")
+%>
+	<body>
+		<div class="title">
+		  <div class="logo">
+		    <a href="http://incubator.apache.org/sling">
+		      <img border="0" src="/apps/espblog/sling-logo.png"/>
+		    </a>
+		  </div>
+		</div>
+		
+		<div class="menu">
+			<%
+			load("menu.esp");
+			%>
+       </div>
+       
+       <div class="main">
+			<h1><%= pageTitle %></h1>
+					
+			  <table>
+			    <tr>
+			      <th>Title</th>
+			
+			      <th>Date</th>
+			      <th colspan="2">Controls</th>
+			    </tr>
+			    
+			    <%
+			    df = new java.text.SimpleDateFormat( "yyyy-MM-dd HH:mm" );
+			
+			    posts = currentNode.getNodes()
+			    for (a in posts) {
+			    	post = posts[a]
+			        if(!post.created) {
+			          // does not look like one of our posts
+			          continue;
+			        }
+			    %>
+			    
+			    <tr>
+			      <td><%=post.title%></td>
+			      <td><%=df.format(post.created.getTime())%></td>
+			      <td><a href="/content/espblog/posts/<%=a%>.html">View</a>&nbsp;<a href="/content/espblog/posts/<%=a%>.edit.html">Edit</a></td>
+			      <td>
+			        <form method="POST" action="/content/espblog/posts/<%=a%>">
+				          <input name=":redirect" type="hidden" value="/content/espblog/posts.admin.html"/> 
+				          <input name=":operation" type="hidden" value="delete"/> 
+				          <input type="submit" value="Delete">
+			      	</form>			          
+			      </td>
+			    </tr>
+			    
+			  <%}%>
+			  </table>
+		</div>			  
+	</body>
+</html>
\ No newline at end of file

Added: incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/constants.esp
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/constants.esp?rev=721453&view=auto
==============================================================================
--- incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/constants.esp (added)
+++ incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/constants.esp Fri Nov 28 04:29:48 2008
@@ -0,0 +1,22 @@
+<% 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+%>
+
+<%
+BLOG_TITLE="Sling ESP blog sample";
+%>
\ No newline at end of file

Added: incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/edit.esp
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/edit.esp?rev=721453&view=auto
==============================================================================
--- incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/edit.esp (added)
+++ incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/edit.esp Fri Nov 28 04:29:48 2008
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+
+<% 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+%>
+
+<html>
+<%
+pageTitle = currentNode.title ? currentNode.title : "New post";
+load("header.esp");
+%>
+	<body>
+		
+		<div class="title">
+		  <div class="logo">
+		    <a href="http://incubator.apache.org/sling">
+		      <img border="0" src="/apps/espblog/sling-logo.png"/>
+		    </a>
+		  </div>
+		</div>
+		
+		<div class="menu">
+			<%
+			load("menu.esp");
+			%>
+       </div>
+       
+       <div class="main">
+			<h1><%= pageTitle %></h1>
+					
+			<form class="hform" method="POST" action="<%= currentNode.getPath().lastIndexOf("*") != currentNode.getPath().length-1 ? currentNode : "/content/espblog/posts/*" %>" enctype="multipart/form-data">	        				
+					
+					<p><label>Title</label>
+					<input name="title" type="text" size="80" value="<%= currentNode.getPath().lastIndexOf("*") != currentNode.getPath().length-1 ? currentNode.title : "" %>"></p>
+					
+					<p><label>Body</label>
+					<textarea name="posttext" cols="40" rows="5"><%= currentNode.getPath().lastIndexOf("*") != currentNode.getPath().length-1 ? currentNode.posttext : "" %></textarea></p>
+					
+					<p><label>File</label><input type="file" name="attachments/*"/></p>
+
+					
+					<input type="hidden" name="created"/> 
+					<input name=":redirect" type="hidden" value="/content/espblog/posts.admin.html"/> 
+												
+				<input type="submit" value="Post" class="button">
+			</form>
+		</div>					
+	</body>
+</html>

Added: incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/espblog.css
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/espblog.css?rev=721453&view=auto
==============================================================================
--- incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/espblog.css (added)
+++ incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/espblog.css Fri Nov 28 04:29:48 2008
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* @override http://incubator.apache.org/sling/site/media.data/site.css */
+
+body { background-color: #ffffff; color: #3b3b3b; font-family: Tahoma, Arial, sans-serif; font-size: 10pt; line-height: 140% }
+h1, h2, h3, h4, h5, h6 { font-weight: normal; color: #000000; line-height: 100%; }
+h1 { font-size: 200% }
+h2 { font-size: 175% }
+h3 { font-size: 150% }
+h4 { font-size: 140% }
+h5 { font-size: 130% }
+h6 { font-size: 120% }
+a { color: #1980af }
+a:visited { color: #1980af }
+a:hover { color: #1faae9 }
+.title { position: absolute; left: 1px; right: 1px; top:25px; height: 81px; background: url(http://incubator.apache.org/sling/site/media.data/gradient.png) repeat-x; background-position: bottom; }
+.logo { position: absolute; width: 15em; height: 81px; text-align: center; }
+.header { text-align: right; margin-right: 20pt; }
+.menu { border-top: 10px solid #f9bb00; position: absolute; top: 107px; left: 1px; width: 15em; bottom: 0px; padding: 0px; background-color: #fcfcfc }
+.menu ul { background-color: #fdf5d9; list-style: none; padding-left: 4em; margin-top: 0px; padding-top: 2em; padding-bottom: 2em; margin-left: 0px; color: #4a4a43}
+.menu a { text-decoration: none; color: #4a4a43 }
+.main { position: absolute; border-top: 10px solid #cde0ea; top: 107px; left: 15em; right: 1px; margin-left: 2px; padding-right: 4em; padding-left: 1em; padding-top: 1em;}
+.code { color: black; background-color: #eeeeee; border: solid 1px black; margin-top: 0.5em; margin-bottom: 0.5em; }
+.codeHeader { text-align: center; font-family: monospace; border-bottom:1px solid black; padding-top: 0.5em; padding-bottom: 0.5em; margin-bottom: 0.5em; }
+.codeContent { padding: 0.5em }
+.codeContent pre { margin: 0em }
+.code-keyword { color: #880000 }
+.code-quote { color: #008800 }
+.code-object { color: #0000dd }
+.code-java { margin: 0em }
+.preformatted { color: black; background-color: #eeeeee; border: solid 1px black; padding: 0.5em }
+.preformattedContent pre { margin: 0em }
+table.confluenceTable { border-collapse:collapse; margin:5px; }
+table.confluenceTable th.confluenceTh { background-color:#FDF5D9; border:1px solid #CCCCCC; padding:3px 4px; text-align:center; }
+table.confluenceTable td.confluenceTd { border:1px solid #CCCCCC; padding:3px 4px; }
+.infoMacro { background-color: #D8E4F1; border: 1px solid #3C78B5; }
+.noteMacro { background-color: #FFFFCE; border: 1px solid #F0C000; }
+.tipMacro { background-color: #DDFFDD; border: 1px solid #009900; }
+.warningMacro { background-color: #FFCCCC; border: 1px solid #CC0000; }
+.note { font-size: 80%; }
\ No newline at end of file

Propchange: incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/espblog.css
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/espblog.css
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/espblog.css
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/header.esp
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/header.esp?rev=721453&view=auto
==============================================================================
--- incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/header.esp (added)
+++ incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/header.esp Fri Nov 28 04:29:48 2008
@@ -0,0 +1,31 @@
+<% 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+%>
+
+<%
+load("constants.esp");
+if(typeof(pageTitle) == "undefined") {
+  pageTitle = BLOG_TITLE;
+}
+%>
+
+<head>
+	<link rel="stylesheet" href="/apps/espblog/espblog.css" type="text/css" media="screen" charset="utf-8">
+	<link rel="alternate" type="application/rss+xml" title="RSS Entries" href="http://<%=request.getServerName()%>:<%=request.getServerPort()%>/content/espblog/posts.xml"/>		
+	<title><%= pageTitle %></title>
+</head>
\ No newline at end of file

Added: incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/html.esp
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/html.esp?rev=721453&view=auto
==============================================================================
--- incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/html.esp (added)
+++ incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/html.esp Fri Nov 28 04:29:48 2008
@@ -0,0 +1,103 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+
+<% 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+%>
+
+<html>
+<%
+load("header.esp");
+load("constants.esp");
+
+function render(attachmentNode) {
+  if(attachmentNode.getNode("jcr:content").getProperty("jcr:mimeType").getString().substring(0,5) == "image") {
+    %><p><img src="<%=attachmentNode%>"></p><%
+  } else {	
+    %><p><a href="<%=attachmentNode%>">Download <%=attachmentNode.getName()%></a></p><%
+  }    
+}
+
+function renderMedia(postNode, mediaFolderName) {
+	if(postNode.hasNode(mediaFolderName)) {
+		%><h3><%= mediaFolderName %></h3><%
+		var nodes = currentNode.getNode(mediaFolderName).getNodes();
+		for(i in nodes) {
+	      render(nodes[i]);
+		}
+	}
+}
+%>
+	<body>
+		<div class="title">
+		  <div class="logo">
+		    <a href="http://incubator.apache.org/sling">
+		      <img border="0" src="/apps/espblog/sling-logo.png"/>
+		    </a>
+		  </div>
+		</div>
+		
+		<div class="menu">
+			<%
+			load("menu.esp");
+			%>
+       </div>
+       
+       <div class="main">
+			<h1><%= BLOG_TITLE %></h1>
+			<div id="postbody">	
+				<h2><%=currentNode.title ? currentNode.title : ""%></h2>	
+				<p><%=currentNode.posttext ? currentNode.posttext : ""%></p>
+				
+				<%
+				if(currentNode.hasNode("comments")) {
+				    %><h3>Comments</h3><%
+					comments = currentNode.getNode("comments").getNodes()
+					for (a in comments) {
+						comment = comments[a]
+						if(comment.commenttext){
+					%>
+					
+					<div>
+					<%=comment.commenter ? comment.commenter : "an anonymous coward"%> said:
+					<p><%=comment.commenttext%></p>	
+					</div>
+				
+				<%
+						}
+					}
+				}
+				%>
+						
+				<% if(currentNode.title) { %>							
+			    <h3>Comment on this post</h3>
+				<form class="hform" method="POST" action="<%=currentNode%>/comments/*">
+					<p><label>Your name</label><input type="text" size="80" name="commenter"/></p>
+					<p><label>Your comment</label>
+					<textarea name="commenttext" cols="40"></textarea></p>
+					<input name=":redirect" type="hidden" value="<%=currentNode%>.view.html"/> 
+					<input type="submit" value="Submit" class="button"/>
+				</form>
+				<% } %>
+			</div>
+			<div id="resources">
+				<% renderMedia(currentNode, "attachments"); %>
+				<% renderMedia(currentNode, "thumbnails"); %>
+			</div>
+		</div>			
+	</body>
+</html>

Added: incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/list.esp
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/list.esp?rev=721453&view=auto
==============================================================================
--- incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/list.esp (added)
+++ incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/list.esp Fri Nov 28 04:29:48 2008
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+
+<% 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+%>
+
+<%    
+   var queryManager = currentNode.getSession().getWorkspace().getQueryManager();  
+   if(request.getParameter('qt')) {
+   	var query = queryManager.createQuery("/jcr:root/content/espblog/posts/element(*, nt:unstructured)[jcr:contains(., '"+request.getParameter("qt")+"')] order by @created descending", "xpath");
+   } else { 
+   	var query = queryManager.createQuery("/jcr:root/content/espblog/posts/element(*, nt:unstructured) order by @created descending", "xpath");
+   }
+   var result = query.execute().getNodes();
+%>
+
+<html>
+
+	<%
+	load("header.esp");
+	%>
+
+	<body>
+		<div class="title">
+		  <div class="logo">
+		    <a href="http://incubator.apache.org/sling">
+		      <img border="0" src="/apps/espblog/sling-logo.png"/>
+		    </a>
+		  </div>
+		</div>
+		
+		<div class="menu">
+			<%
+			load("menu.esp");
+			%>
+       </div>
+       
+       <div class="main">
+			<h1><%= pageTitle %></h1>
+			<h2><%= request.getParameter('qt') ? "Search results" : "Recent posts" %></h2>
+		
+			<div id="postbody">
+				<%
+			        df = new Packages.java.text.SimpleDateFormat( "yyyy-MM-dd HH:mm" );
+	
+			        while(result.hasNext()) {
+			        	post = result.nextNode()
+			        %> 
+	
+					<h3><a href="<%= post.getPath() %>.html"><%=post.title%></a></h3>
+					<strong>Posted at <%=df.format(post.created.getTime())%></strong><br>					
+					<p><%=post.posttext%><br/><strong class="highlight"><a href="<%=post%>.html"><%=post.hasNode("comments") ? "See comments" : "Be the first to comment"%> </a></strong> </p>
+				<%}%>	
+			</div>
+		</div>			
+	</body>
+</html>
\ No newline at end of file

Added: incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/menu.esp
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/menu.esp?rev=721453&view=auto
==============================================================================
--- incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/menu.esp (added)
+++ incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/menu.esp Fri Nov 28 04:29:48 2008
@@ -0,0 +1,32 @@
+<% 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+%>
+
+<%
+load("constants.esp");
+%>
+
+<div id="header">				
+	<ul class="tabs">
+		<li><a href="/content/espblog/posts.list.html">Home</a></li>
+		<li><a href="/content/espblog/posts.admin.html">Admin</a></li>
+		<li><a href="/content/espblog/posts/*.edit.html">New Post</a></li>
+		<li><a href="/content/espblog/posts.xml">RSS feed</a></li>
+		<li><form method="GET" action="/content/espblog/posts.list.html"><input type="text" name="qt" size="10" value="Search"/></form></li>	
+	</ul>
+</div>
\ No newline at end of file

Added: incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/sling-logo.png
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/sling-logo.png?rev=721453&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/sling-logo.png
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/sling-logo.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/xml.esp
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/xml.esp?rev=721453&view=auto
==============================================================================
--- incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/xml.esp (added)
+++ incubator/sling/trunk/samples/espblog/src/main/resources/initial-content/apps/espblog/xml.esp Fri Nov 28 04:29:48 2008
@@ -0,0 +1,55 @@
+<?xml version="1.0"?>
+
+<% 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+%>
+
+<%    
+   var queryManager = currentNode.getSession().getWorkspace().getQueryManager();  
+   var query = queryManager.createQuery("/jcr:root/content/espblog/posts/element(*, nt:unstructured) order by @created descending", "xpath");
+   var result = query.execute().getNodes();
+   
+%>
+
+<rss version="2.0">
+   <channel>
+      <title>My Sling Blog</title>
+      <link><%=request.getRequestURL()%></link>
+      <description>RSS 2.0 feed of my Sling blog</description>
+      
+      <%
+      	df = new java.text.SimpleDateFormat( "EEE', 'dd' 'MMM' 'yyyy' 'HH:mm:ss' 'Z", Packages.java.util.Locale.US);
+	var counter = 0;
+	while(result.hasNext() && counter < 10) {
+		counter++;
+		post = result.nextNode()
+      %>
+      
+      <item>
+         <title><%=post.title%></title>
+         <link>http://<%=request.getServerName()%>:<%=request.getServerPort()%><%=post%>.html</link>
+         <description><%=post.posttext%></description>
+         <pubDate><%=df.format(post.created.getTime())%></pubDate>
+      </item>
+      
+      <%
+      }
+      %>
+     
+   </channel>
+</rss>
\ No newline at end of file