SLING-7625 refactoring of the code base

Remove all uses of deprecated API's
Remove all methods that aren't being used
Re-organize GET servlets to be in one location
Rename objects to better represent their purpose
Reduce memory consumption by removing unnecessary Object creation
diff --git a/src/main/java/org/apache/sling/servlets/get/impl/DefaultGetServlet.java b/src/main/java/org/apache/sling/servlets/get/impl/DefaultGetServlet.java
index e045a4b..45b2090 100644
--- a/src/main/java/org/apache/sling/servlets/get/impl/DefaultGetServlet.java
+++ b/src/main/java/org/apache/sling/servlets/get/impl/DefaultGetServlet.java
@@ -32,11 +32,12 @@
 import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
 import org.apache.sling.servlets.get.impl.helpers.HeadServletResponse;
-import org.apache.sling.servlets.get.impl.helpers.HtmlRendererServlet;
-import org.apache.sling.servlets.get.impl.helpers.JsonRendererServlet;
-import org.apache.sling.servlets.get.impl.helpers.PlainTextRendererServlet;
-import org.apache.sling.servlets.get.impl.helpers.StreamRendererServlet;
-import org.apache.sling.servlets.get.impl.helpers.XMLRendererServlet;
+import org.apache.sling.servlets.get.impl.helpers.HtmlRenderer;
+import org.apache.sling.servlets.get.impl.helpers.JsonRenderer;
+import org.apache.sling.servlets.get.impl.helpers.PlainTextRenderer;
+import org.apache.sling.servlets.get.impl.helpers.Renderer;
+import org.apache.sling.servlets.get.impl.helpers.StreamRenderer;
+import org.apache.sling.servlets.get.impl.helpers.XMLRenderer;
 import org.apache.sling.xss.XSSAPI;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
@@ -131,7 +132,7 @@
 
     private final Logger logger = LoggerFactory.getLogger(getClass());
 
-    private Map<String, Servlet> rendererMap = new HashMap<>();
+    private Map<String, Renderer> rendererMap = new HashMap<>();
 
     private int jsonMaximumResults;
 
@@ -188,31 +189,18 @@
         this.indexFiles = null;
     }
 
-    private Servlet getDefaultRendererServlet(final String type) {
-        Servlet servlet = null;
+    private Renderer getDefaultRendererServlet(final String type) {
+    	Renderer servlet = null;
         if ( EXT_RES.equals(type) ) {
-            servlet = new StreamRendererServlet(index, indexFiles);
+            servlet = new StreamRenderer(index, indexFiles, getServletContext());
         } else if ( EXT_HTML.equals(type) ) {
-            servlet = new HtmlRendererServlet(xssApi);
+            servlet = new HtmlRenderer(xssApi);
         } else if ( EXT_TXT.equals(type) ) {
-            servlet = new PlainTextRendererServlet();
+            servlet = new PlainTextRenderer();
         } else if (EXT_JSON.equals(type) ) {
-            servlet = new JsonRendererServlet(jsonMaximumResults);
+            servlet = new JsonRenderer(jsonMaximumResults);
         } else if ( EXT_XML.equals(type) ) {
-            try {
-                servlet = new XMLRendererServlet();
-            } catch (Throwable t) {
-                logger.warn("Support for getting XML is currently disabled " +
-                        "in the servlets get module. Check whether the JCR API is available.");
-            }
-        }
-        if ( servlet != null ) {
-            try {
-                servlet.init(getServletConfig());
-            } catch (Throwable t) {
-                logger.error("Error while initializing servlet " + servlet, t);
-                servlet = null;
-            }
+            servlet = new XMLRenderer();
         }
         return servlet;
     }
@@ -223,7 +211,7 @@
 
         // use the servlet for rendering StreamRendererServlet.EXT_RES as the
         // streamer servlet
-        Servlet streamerServlet = getDefaultRendererServlet(EXT_RES);
+        Renderer streamerServlet = getDefaultRendererServlet(EXT_RES);
 
         rendererMap.put(null, streamerServlet);
         
@@ -256,7 +244,7 @@
                 final int pos = m.indexOf(':');
                 if (pos != -1) {
                     final String type = m.substring(0, pos);
-                    Servlet servlet = rendererMap.get(type);
+                    Renderer servlet = rendererMap.get(type);
                     if ( servlet == null ) {
                         servlet = getDefaultRendererServlet(type);
                     }
@@ -291,7 +279,7 @@
                 request.getResource().getPath(), "No resource found");
         }
 
-        Servlet rendererServlet;
+        Renderer rendererServlet;
         String ext = request.getRequestPathInfo().getExtension();
         rendererServlet = rendererMap.get(ext);
 
@@ -316,7 +304,7 @@
         request.getRequestProgressTracker().log(
             "Using " + rendererServlet.getClass().getName()
                 + " to render for extension=" + ext);
-        rendererServlet.service(request, response);
+        rendererServlet.render(request, response);
     }
 
     @Override
@@ -330,17 +318,7 @@
 
     @Override
     public void destroy() {
-
-        for (Servlet servlet : rendererMap.values()) {
-            try {
-                servlet.destroy();
-            } catch (Throwable t) {
-                logger.error("Error while destroying servlet " + servlet, t);
-            }
-        }
-
         rendererMap.clear();
-
         super.destroy();
     }
 }
diff --git a/src/main/java/org/apache/sling/servlets/get/impl/impl/info/SlingInfoServlet.java b/src/main/java/org/apache/sling/servlets/get/impl/SlingInfoServlet.java
similarity index 98%
rename from src/main/java/org/apache/sling/servlets/get/impl/impl/info/SlingInfoServlet.java
rename to src/main/java/org/apache/sling/servlets/get/impl/SlingInfoServlet.java
index 8e902c4..9f3e470 100644
--- a/src/main/java/org/apache/sling/servlets/get/impl/impl/info/SlingInfoServlet.java
+++ b/src/main/java/org/apache/sling/servlets/get/impl/SlingInfoServlet.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.sling.servlets.get.impl.impl.info;
+package org.apache.sling.servlets.get.impl;
 
 import java.io.IOException;
 import java.io.PrintWriter;
diff --git a/src/main/java/org/apache/sling/servlets/get/impl/version/VersionInfoServlet.java b/src/main/java/org/apache/sling/servlets/get/impl/VersionInfoServlet.java
similarity index 96%
rename from src/main/java/org/apache/sling/servlets/get/impl/version/VersionInfoServlet.java
rename to src/main/java/org/apache/sling/servlets/get/impl/VersionInfoServlet.java
index a9d806e..31b786c 100644
--- a/src/main/java/org/apache/sling/servlets/get/impl/version/VersionInfoServlet.java
+++ b/src/main/java/org/apache/sling/servlets/get/impl/VersionInfoServlet.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.sling.servlets.get.impl.version;
+package org.apache.sling.servlets.get.impl;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -44,7 +44,7 @@
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
 import org.apache.sling.servlets.get.impl.util.JsonObjectCreator;
-import org.apache.sling.servlets.get.impl.util.JsonRenderer;
+import org.apache.sling.servlets.get.impl.util.JsonToText;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.ConfigurationPolicy;
 import org.osgi.service.metatype.annotations.AttributeDefinition;
@@ -92,7 +92,7 @@
     /** How much to indent in tidy mode */
     public static final int INDENT_SPACES = 2;
     
-    private final JsonRenderer renderer = new JsonRenderer();
+    private final JsonToText renderer = new JsonToText();
 
     @Override
     public void doGet(SlingHttpServletRequest req, SlingHttpServletResponse resp) throws ServletException,
@@ -102,7 +102,7 @@
         final boolean tidy = hasSelector(req, TIDY);
         final boolean harray = hasSelector(req, HARRAY);
 
-        final JsonRenderer.Options opt = renderer.options().withIndent(tidy ? INDENT_SPACES : 0)
+        final JsonToText.Options opt = renderer.options().withIndent(tidy ? INDENT_SPACES : 0)
                     .withArraysForChildren(harray);
         
         try {
diff --git a/src/main/java/org/apache/sling/servlets/get/impl/helpers/HeadServletResponse.java b/src/main/java/org/apache/sling/servlets/get/impl/helpers/HeadServletResponse.java
index 238f85e..9b627c8 100644
--- a/src/main/java/org/apache/sling/servlets/get/impl/helpers/HeadServletResponse.java
+++ b/src/main/java/org/apache/sling/servlets/get/impl/helpers/HeadServletResponse.java
@@ -17,7 +17,6 @@
 
 package org.apache.sling.servlets.get.impl.helpers;
 
-
 import java.io.PrintWriter;
 import java.io.Writer;
 
@@ -29,110 +28,108 @@
 
 /**
  * The <code>HeadServletResponse</code> is a Sling response wrapper which
- * ensures that nothing will ever be written by return null writers or
- * output streams.
+ * ensures that nothing will ever be written by return null writers or output
+ * streams.
  */
 
-public class HeadServletResponse extends
-        SlingHttpServletResponseWrapper {
+public class HeadServletResponse extends SlingHttpServletResponseWrapper {
 
-    private ServletOutputStream stream;
+	private ServletOutputStream stream;
 
-    private PrintWriter writer;
+	private PrintWriter writer;
 
-    public HeadServletResponse(SlingHttpServletResponse wrappedResponse) {
-        super(wrappedResponse);
-    }
+	public HeadServletResponse(SlingHttpServletResponse wrappedResponse) {
+		super(wrappedResponse);
+	}
 
-    @Override
-    public ServletOutputStream getOutputStream() {
-        if (writer != null) {
-            throw new IllegalStateException("Writer already obtained");
-        }
+	@Override
+	public ServletOutputStream getOutputStream() {
+		if (writer != null) {
+			throw new IllegalStateException("Writer already obtained");
+		}
 
-        if (stream == null) {
-            stream = new NullServletOutputStream();
-        }
+		if (stream == null) {
+			stream = new NullServletOutputStream();
+		}
 
-        return stream;
-    }
+		return stream;
+	}
 
-    @Override
-    public PrintWriter getWriter() {
-        if (stream != null) {
-            throw new IllegalStateException("OutputStream already obtained");
-        }
+	@Override
+	public PrintWriter getWriter() {
+		if (stream != null) {
+			throw new IllegalStateException("OutputStream already obtained");
+		}
 
-        if (writer == null) {
-            writer = new PrintWriter(new NullWriter());
-        }
+		if (writer == null) {
+			writer = new PrintWriter(new NullWriter());
+		}
 
-        return writer;
-    }
+		return writer;
+	}
 
-    /**
-     * The <code>NullServletOutputStream</code> is a
-     * <code>ServletOutputStream</code> which simply does not write out
-     * anything.
-     *
-     * @see HeadServletResponse#getOutputStream()
-     */
-    private static class NullServletOutputStream extends ServletOutputStream {
-        @Override
-        public void write(int b) {
-        }
+	/**
+	 * The <code>NullServletOutputStream</code> is a
+	 * <code>ServletOutputStream</code> which simply does not write out anything.
+	 *
+	 * @see HeadServletResponse#getOutputStream()
+	 */
+	private static class NullServletOutputStream extends ServletOutputStream {
+		@Override
+		public void write(int b) {
+		}
 
-        @Override
-        public void write(byte[] b) {
-        }
+		@Override
+		public void write(byte[] b) {
+		}
 
-        @Override
-        public void write(byte[] b, int off, int len) {
-        }
+		@Override
+		public void write(byte[] b, int off, int len) {
+		}
 
-        @Override
-        public boolean isReady() {
-            return true;
-        }
+		@Override
+		public boolean isReady() {
+			return true;
+		}
 
-        @Override
-        public void setWriteListener(WriteListener writeListener) {
-        }
-    }
+		@Override
+		public void setWriteListener(WriteListener writeListener) {
+		}
+	}
 
-    /**
-     * The <code>NullWriter</code> is a <code>Writer</code> which simply does
-     * not write out anything.
-     *
-     * @see HeadServletResponse#getWriter()
-     */
-    private static class NullWriter extends Writer {
-        @Override
-        public void write(char[] cbuf, int off, int len) {
-        }
+	/**
+	 * The <code>NullWriter</code> is a <code>Writer</code> which simply does not
+	 * write out anything.
+	 *
+	 * @see HeadServletResponse#getWriter()
+	 */
+	private static class NullWriter extends Writer {
+		@Override
+		public void write(char[] cbuf, int off, int len) {
+		}
 
-        @Override
-        public void write(char[] cbuf) {
-        }
+		@Override
+		public void write(char[] cbuf) {
+		}
 
-        @Override
-        public void write(int c) {
-        }
+		@Override
+		public void write(int c) {
+		}
 
-        @Override
-        public void write(String str) {
-        }
+		@Override
+		public void write(String str) {
+		}
 
-        @Override
-        public void write(String str, int off, int len) {
-        }
+		@Override
+		public void write(String str, int off, int len) {
+		}
 
-        @Override
-        public void flush() {
-        }
+		@Override
+		public void flush() {
+		}
 
-        @Override
-        public void close() {
-        }
-    }
+		@Override
+		public void close() {
+		}
+	}
 }
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/servlets/get/impl/helpers/HtmlRendererServlet.java b/src/main/java/org/apache/sling/servlets/get/impl/helpers/HtmlRenderer.java
similarity index 92%
rename from src/main/java/org/apache/sling/servlets/get/impl/helpers/HtmlRendererServlet.java
rename to src/main/java/org/apache/sling/servlets/get/impl/helpers/HtmlRenderer.java
index 8168e13..2b00fac 100644
--- a/src/main/java/org/apache/sling/servlets/get/impl/helpers/HtmlRendererServlet.java
+++ b/src/main/java/org/apache/sling/servlets/get/impl/helpers/HtmlRenderer.java
@@ -20,7 +20,6 @@
 import java.io.PrintWriter;
 import java.util.Map;
 
-import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.sling.api.SlingConstants;
@@ -29,29 +28,23 @@
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceNotFoundException;
 import org.apache.sling.api.resource.ResourceUtil;
-import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
 import org.apache.sling.xss.XSSAPI;
 
 /**
  * The <code>HtmlRendererServlet</code> renders the current resource in HTML
  * on behalf of the {@link org.apache.sling.servlets.get.impl.DefaultGetServlet}.
  */
-public class HtmlRendererServlet extends SlingSafeMethodsServlet {
-
-    private static final long serialVersionUID = -5815904221043005085L;
-
-
+public class HtmlRenderer implements Renderer  {
 
     private final XSSAPI xssApi;
 
-    public HtmlRendererServlet(final XSSAPI xssApi) {
+    public HtmlRenderer(final XSSAPI xssApi) {
         this.xssApi = xssApi;
     }
 
-    @Override
-    protected void doGet(final SlingHttpServletRequest req,
-            final SlingHttpServletResponse resp)
-    throws ServletException, IOException {
+
+    public void render(final SlingHttpServletRequest req,
+            final SlingHttpServletResponse resp) throws IOException {
         final Resource r = req.getResource();
 
         if (ResourceUtil.isNonExistingResource(r)) {
diff --git a/src/main/java/org/apache/sling/servlets/get/impl/helpers/JsonRendererServlet.java b/src/main/java/org/apache/sling/servlets/get/impl/helpers/JsonRenderer.java
similarity index 93%
rename from src/main/java/org/apache/sling/servlets/get/impl/helpers/JsonRendererServlet.java
rename to src/main/java/org/apache/sling/servlets/get/impl/helpers/JsonRenderer.java
index 7a436d7..f8fbbed 100644
--- a/src/main/java/org/apache/sling/servlets/get/impl/helpers/JsonRendererServlet.java
+++ b/src/main/java/org/apache/sling/servlets/get/impl/helpers/JsonRenderer.java
@@ -30,8 +30,7 @@
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceNotFoundException;
 import org.apache.sling.api.resource.ResourceUtil;
-import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
-import org.apache.sling.servlets.get.impl.util.JsonRenderer;
+import org.apache.sling.servlets.get.impl.util.JsonToText;
 import org.apache.sling.servlets.get.impl.util.ResourceTraversor;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -40,11 +39,9 @@
  * The <code>JsonRendererServlet</code> renders the current resource in JSON
  * on behalf of the {@link org.apache.sling.servlets.get.impl.DefaultGetServlet}.
  */
-public class JsonRendererServlet extends SlingSafeMethodsServlet {
+public class JsonRenderer implements Renderer {
 
-    private final Logger log = LoggerFactory.getLogger(JsonRendererServlet.class);
-
-    private static final long serialVersionUID = 5577121546674133317L;
+    private final Logger log = LoggerFactory.getLogger(JsonRenderer.class);
 
     /** Recursion level selector that means "all levels" */
     public static final String INFINITY = "infinity";
@@ -62,14 +59,13 @@
 
     private long maximumResults;
 
-    private final JsonRenderer renderer = new JsonRenderer();
+    private final JsonToText renderer = new JsonToText();
 
-    public JsonRendererServlet(long maximumResults) {
+    public JsonRenderer(long maximumResults) {
         this.maximumResults = maximumResults;
     }
 
-    @Override
-    protected void doGet(SlingHttpServletRequest req,
+    public void render(SlingHttpServletRequest req,
             SlingHttpServletResponse resp) throws IOException {
         // Access and check our data
         final Resource r = req.getResource();
@@ -107,7 +103,7 @@
             // Dump the resource if we can
             if (allowDump) {
                 if (tidy || harray) {
-                    final JsonRenderer.Options opt = renderer.options()
+                    final JsonToText.Options opt = renderer.options()
                             .withIndent(tidy ? INDENT_SPACES : 0)
                             .withArraysForChildren(harray);
                     resp.getWriter().write(renderer.prettyPrint(traversor.getJSONObject(), opt));
diff --git a/src/main/java/org/apache/sling/servlets/get/impl/helpers/PlainTextRendererServlet.java b/src/main/java/org/apache/sling/servlets/get/impl/helpers/PlainTextRenderer.java
similarity index 91%
rename from src/main/java/org/apache/sling/servlets/get/impl/helpers/PlainTextRendererServlet.java
rename to src/main/java/org/apache/sling/servlets/get/impl/helpers/PlainTextRenderer.java
index bf66e09..6bbc6bc 100644
--- a/src/main/java/org/apache/sling/servlets/get/impl/helpers/PlainTextRendererServlet.java
+++ b/src/main/java/org/apache/sling/servlets/get/impl/helpers/PlainTextRenderer.java
@@ -21,7 +21,6 @@
 import java.util.Iterator;
 import java.util.Map;
 
-import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.sling.api.SlingHttpServletRequest;
@@ -29,20 +28,17 @@
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceNotFoundException;
 import org.apache.sling.api.resource.ResourceUtil;
-import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
 
 /**
  * The <code>PlainTextRendererServlet</code> renders the current resource in
  * plain text on behalf of the
  * {@link org.apache.sling.servlets.get.impl.DefaultGetServlet}.
  */
-public class PlainTextRendererServlet extends SlingSafeMethodsServlet {
+public class PlainTextRenderer implements Renderer {
 
-    private static final long serialVersionUID = -5815904221043005085L;
 
-    @Override
-    protected void doGet(SlingHttpServletRequest req,
-            SlingHttpServletResponse resp) throws ServletException, IOException {
+    public void render(SlingHttpServletRequest req,
+            SlingHttpServletResponse resp) throws IOException {
         final Resource r = req.getResource();
         if (ResourceUtil.isNonExistingResource(r)) {
             throw new ResourceNotFoundException("No data to render.");
diff --git a/src/main/java/org/apache/sling/servlets/get/impl/helpers/Renderer.java b/src/main/java/org/apache/sling/servlets/get/impl/helpers/Renderer.java
new file mode 100644
index 0000000..4b7bd0e
--- /dev/null
+++ b/src/main/java/org/apache/sling/servlets/get/impl/helpers/Renderer.java
@@ -0,0 +1,29 @@
+/*

+ * 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.servlets.get.impl.helpers;

+

+import java.io.IOException;

+

+import org.apache.sling.api.SlingHttpServletRequest;

+import org.apache.sling.api.SlingHttpServletResponse;

+

+public interface Renderer {

+

+	void render(final SlingHttpServletRequest req, final SlingHttpServletResponse resp) throws IOException;

+

+}

diff --git a/src/main/java/org/apache/sling/servlets/get/impl/helpers/StreamRendererServlet.java b/src/main/java/org/apache/sling/servlets/get/impl/helpers/StreamRenderer.java
similarity index 95%
rename from src/main/java/org/apache/sling/servlets/get/impl/helpers/StreamRendererServlet.java
rename to src/main/java/org/apache/sling/servlets/get/impl/helpers/StreamRenderer.java
index f89fa46..c39199c 100644
--- a/src/main/java/org/apache/sling/servlets/get/impl/helpers/StreamRendererServlet.java
+++ b/src/main/java/org/apache/sling/servlets/get/impl/helpers/StreamRenderer.java
@@ -32,6 +32,7 @@
 import java.util.StringTokenizer;
 
 import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
@@ -50,7 +51,6 @@
 import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.api.resource.external.ExternalizableInputStream;
 import org.apache.sling.api.servlets.HttpConstants;
-import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
 import org.apache.sling.servlets.get.impl.DefaultGetServlet;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -60,11 +60,9 @@
  * client on behalf of the
  * {@link org.apache.sling.servlets.get.impl.DefaultGetServlet}. If the current
  * resource cannot be streamed it is rendered using the
- * {@link PlainTextRendererServlet}.
+ * {@link PlainTextRenderer}.
  */
-public class StreamRendererServlet extends SlingSafeMethodsServlet {
-
-    private static final long serialVersionUID = -1L;
+public class StreamRenderer implements Renderer {
 
     /**
      * MIME multipart separation string
@@ -94,31 +92,17 @@
 
     private String[] indexFiles;
 
-    public StreamRendererServlet(boolean index, String[] indexFiles) {
+	private ServletContext context;
+
+    public StreamRenderer(boolean index, String[] indexFiles,ServletContext context) {
         this.index = index;
         this.indexFiles = indexFiles;
+        this.context = context;
     }
 
-    @Override
-    protected void doGet(SlingHttpServletRequest request,
-            SlingHttpServletResponse response) throws ServletException,
-            IOException {
-
-        processRequest(request, response);
-
-    }
-
-    @Override
-    protected void doHead(SlingHttpServletRequest request,
-                         SlingHttpServletResponse response) throws ServletException,
-            IOException {
-        processRequest(request, response);
-    }
-
-    private void processRequest(SlingHttpServletRequest request,
-                                   SlingHttpServletResponse response) throws ServletException,
-            IOException {
-
+    public void render(SlingHttpServletRequest request,
+            SlingHttpServletResponse response) throws IOException {
+    	
         // whether this servlet is called as of a request include
         final boolean included = request.getAttribute(SlingConstants.ATTR_REQUEST_SERVLET) != null;
 
@@ -245,12 +229,10 @@
 
             final ArrayList<Range> ranges;
             if (included) {
-
                 // no range support on included requests
                 ranges = FULL;
 
             } else {
-
                 // parse optional ranges
                 ranges = parseRange(request, response,
                     resource.getResourceMetadata());
@@ -267,7 +249,6 @@
             ServletOutputStream out = response.getOutputStream();
 
             if (ranges == FULL) {
-
                 // return full resource
                 setContentLength(response,
                     resource.getResourceMetadata().getContentLength());
@@ -276,21 +257,16 @@
                 while ((rd = stream.read(buf)) >= 0) {
                     out.write(buf, 0, rd);
                 }
-
             } else {
-
                 // return ranges of the resource
                 response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
 
                 if (ranges.size() == 1) {
-
                     Range range = ranges.get(0);
                     response.addHeader("Content-Range", "bytes " + range.start
                         + "-" + range.end + "/" + range.length);
                     setContentLength(response, range.end - range.start + 1);
-
                     copy(stream, out, range);
-
                 } else {
 
                     response.setContentType("multipart/byteranges; boundary="
@@ -308,7 +284,7 @@
 
     private void renderDirectory(final SlingHttpServletRequest request,
             final SlingHttpServletResponse response, final boolean included)
-            throws ServletException, IOException {
+            throws IOException {
 
         // request is included or committed, not rendering index
         if (included || response.isCommitted()) {
@@ -345,7 +321,11 @@
                     dispatcher = request.getRequestDispatcher(fileRes, rdo);
                 }
 
-                dispatcher.include(request, response);
+                try {
+					dispatcher.include(request, response);
+				} catch (ServletException e) {
+					throw new IOException(e);
+				}
                 return;
             }
         }
@@ -382,7 +362,7 @@
             // provides the
             // default one,
             // try to do better using our servlet context
-            final String ct = getServletContext().getMimeType(
+            final String ct = context.getMimeType(
                 resource.getPath());
             if (ct != null) {
                 contentType = ct;
diff --git a/src/main/java/org/apache/sling/servlets/get/impl/helpers/XMLRendererServlet.java b/src/main/java/org/apache/sling/servlets/get/impl/helpers/XMLRenderer.java
similarity index 93%
rename from src/main/java/org/apache/sling/servlets/get/impl/helpers/XMLRendererServlet.java
rename to src/main/java/org/apache/sling/servlets/get/impl/helpers/XMLRenderer.java
index 546dc50..cda2b78 100644
--- a/src/main/java/org/apache/sling/servlets/get/impl/helpers/XMLRendererServlet.java
+++ b/src/main/java/org/apache/sling/servlets/get/impl/helpers/XMLRenderer.java
@@ -29,7 +29,6 @@
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceNotFoundException;
 import org.apache.sling.api.resource.ResourceUtil;
-import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
@@ -39,17 +38,15 @@
  *
  * At the moment only JCR nodes can be rendered as XML.
  */
-public class XMLRendererServlet extends SlingSafeMethodsServlet {
-
-    private static final long serialVersionUID = -3520278283206430415L;
+public class XMLRenderer implements Renderer {
 
     private static final String SYSVIEW = "sysview";
     private static final String DOCVIEW = "docview";
 
-    @Override
-    protected void doGet(SlingHttpServletRequest req,
+ 
+    public void render(SlingHttpServletRequest req,
                          SlingHttpServletResponse resp)
-    throws ServletException, IOException {
+    throws IOException {
         final Resource r = req.getResource();
 
         if (ResourceUtil.isNonExistingResource(r)) {
diff --git a/src/main/java/org/apache/sling/servlets/get/impl/util/JsonObjectCreator.java b/src/main/java/org/apache/sling/servlets/get/impl/util/JsonObjectCreator.java
index 6f6b48a..49d8caf 100644
--- a/src/main/java/org/apache/sling/servlets/get/impl/util/JsonObjectCreator.java
+++ b/src/main/java/org/apache/sling/servlets/get/impl/util/JsonObjectCreator.java
@@ -70,10 +70,8 @@
             // the node's actual properties
             while (props.hasNext()) {
                 final Map.Entry<String,Object> prop = props.next();
-
                 if ( prop.getValue() != null ) {
-                    createProperty(obj, valueMap, prop.getKey().toString(),
-                        prop.getValue());
+                    createProperty(obj, valueMap, prop.getKey(), prop.getValue());
                 }
             }
         }
@@ -95,8 +93,9 @@
     }
 
     /** Dump only a value in the correct format */
-    public static JsonValue getValue(final Object value) {
+    private static JsonValue getValue(final Object value) {
         JsonObjectBuilder builder = Json.createObjectBuilder();
+
         if ( value instanceof InputStream ) {
             // input stream is already handled
             builder.add("entry", 0);
@@ -121,7 +120,7 @@
     /**
      * Write a single property
      */
-    public static void createProperty(final JsonObjectBuilder obj,
+    private static void createProperty(final JsonObjectBuilder obj,
                                  final ValueMap valueMap,
                                  final String key,
                                  final Object value) {
diff --git a/src/main/java/org/apache/sling/servlets/get/impl/util/JsonRenderer.java b/src/main/java/org/apache/sling/servlets/get/impl/util/JsonRenderer.java
deleted file mode 100644
index 332d4f8..0000000
--- a/src/main/java/org/apache/sling/servlets/get/impl/util/JsonRenderer.java
+++ /dev/null
@@ -1,503 +0,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.
- */
-package org.apache.sling.servlets.get.impl.util;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.Iterator;
-import java.util.Map;
-
-import javax.json.Json;
-import javax.json.JsonArray;
-import javax.json.JsonArrayBuilder;
-import javax.json.JsonObject;
-import javax.json.JsonObjectBuilder;
-import javax.json.JsonString;
-import javax.json.JsonValue;
-
-public class JsonRenderer
-{
-    /** Rendering options */
-    static public class Options {
-        int indent;
-        private boolean indentIsPositive;
-        int initialIndent;
-        boolean arraysForChildren;
-
-        public static final String DEFAULT_CHILDREN_KEY = "__children__";
-        public static final String DEFAULT_CHILD_NAME_KEY = "__name__";
-
-        String childrenKey = DEFAULT_CHILDREN_KEY;
-        String childNameKey = DEFAULT_CHILD_NAME_KEY;
-
-        /** Clients use JSONRenderer.options() to create objects */
-        private Options() {
-        }
-
-        Options(Options opt) {
-            this.indent = opt.indent;
-            this.indentIsPositive = opt.indentIsPositive;
-            this.initialIndent = opt.initialIndent;
-            this.arraysForChildren = opt.arraysForChildren;
-        }
-
-        public Options withIndent(int n) {
-            indent = n;
-            indentIsPositive = indent > 0;
-            return this;
-        }
-
-        public Options withInitialIndent(int n) {
-            initialIndent = n;
-            return this;
-        }
-
-        public Options withArraysForChildren(boolean b) {
-            arraysForChildren = b;
-            return this;
-        }
-
-        public Options withChildNameKey(String key) {
-            childNameKey = key;
-            return this;
-        }
-
-        public Options withChildrenKey(String key) {
-            childrenKey = key;
-            return this;
-        }
-
-        boolean hasIndent() {
-            return indentIsPositive;
-        }
-    }
-
-    /** Return an Options object with default values */
-    public Options options() {
-        return new Options();
-    }
-
-    /** Write N spaces to sb for indentation */
-    private void indent(StringBuilder sb, int howMuch) {
-        for (int i=0; i < howMuch; i++) {
-            sb.append(' ');
-        }
-    }
-
-    /** Render the supplied JSONObject to a String, in
-     *  the simplest possible way.
-     */
-    public String toString(JsonObject jo) {
-        try {
-            StringWriter writer = new StringWriter();
-            Json.createGenerator(writer).write(jo).close();
-            return writer.toString();
-        } catch (Exception e) {
-            return null;
-        }
-    }
-
-    /** Make a JSON text of the supplied JSONArray. For compactness, no
-     *  unnecessary whitespace is added. If it is not possible to produce a
-     *  syntactically correct JSON text then null will be returned instead. This
-     *  could occur if the array contains an invalid number.
-     *  <p>Warning: This method assumes that the data structure is acyclical.
-     *
-     *  @return a printable, displayable, transmittable
-     *  representation of the array.
-     */
-    public String toString(JsonArray ja) {
-        try {
-            return '[' + join(ja,",") + ']';
-        } catch (Exception e) {
-            return null;
-        }
-    }
-
-    /** Quote the supplied string for JSON */
-    public String quote(String string) {
-        if (string == null || string.length() == 0) {
-            return "\"\"";
-        }
-
-        char          b;
-        char          c = 0;
-        int           i;
-        int           len = string.length();
-        StringBuilder sb = new StringBuilder(len + 2);
-        String        t;
-
-        sb.append('"');
-        for (i = 0; i < len; i += 1) {
-            b = c;
-            c = string.charAt(i);
-            switch (c) {
-                case '\\':
-                case '"':
-                    sb.append('\\');
-                    sb.append(c);
-                    break;
-                case '/':
-                    if (b == '<') {
-                        sb.append('\\');
-                    }
-                    sb.append(c);
-                    break;
-                case '\b':
-                    sb.append("\\b");
-                    break;
-                case '\t':
-                    sb.append("\\t");
-                    break;
-                case '\n':
-                    sb.append("\\n");
-                    break;
-                case '\f':
-                    sb.append("\\f");
-                    break;
-                case '\r':
-                    sb.append("\\r");
-                    break;
-                default:
-                    if (c < ' ' || (c >= '\u0080' && c < '\u00a0') ||
-                            (c >= '\u2000' && c < '\u2100')) {
-                        t = "000" + Integer.toHexString(c);
-                        sb.append("\\u").append(t.substring(t.length() - 4));
-                    } else {
-                        sb.append(c);
-                    }
-            }
-        }
-        sb.append('"');
-        return sb.toString();
-    }
-
-    /** Quote the supplied string for JSON, to the supplied Writer */
-    public void quote(Writer w, String string) throws IOException {
-        w.write(quote(string));
-    }
-
-    /**
-     * Make a JSON text of an Object value. 
-     * <p>
-     * Warning: This method assumes that the data structure is acyclical.
-     * @param value The value to be serialized.
-     * @return a printable, displayable, transmittable
-     *  representation of the object, beginning
-     *  with <code>{</code>&nbsp;<small>(left brace)</small> and ending
-     *  with <code>}</code>&nbsp;<small>(right brace)</small>.
-     * @throws JSONException If the value is or contains an invalid number.
-     */
-    public String valueToString(Object value) {
-        // TODO call the other valueToString instead
-        if (value == null || value.equals(null)) {
-            return "null";
-        }
-        if (value instanceof JsonString) {
-            quote(((JsonString)value).getString());
-        }
-        if (value instanceof Number) {
-            return numberToString((Number) value);
-        }
-        if (value instanceof Boolean) {
-            return value.toString();
-        }
-        if (value instanceof JsonObject || value instanceof JsonArray) {
-            StringWriter writer = new StringWriter();
-            Json.createGenerator(writer).write((JsonValue) value).close();
-            return writer.toString();
-        }
-        return quote(value.toString());
-    }
-
-    /** Make a JSON String of an Object value, with rendering options
-     * <p>
-     * Warning: This method assumes that the data structure is acyclical.
-     * @param value The value to be serialized.
-     * @return a printable, displayable, transmittable
-     *  representation of the object, beginning
-     *  with <code>{</code>&nbsp;<small>(left brace)</small> and ending
-     *  with <code>}</code>&nbsp;<small>(right brace)</small>.
-     * @throws JSONException If the object contains an invalid number.
-     */
-    public String valueToString(Object value, Options opt) {
-        if (value == null || value.equals(null)) {
-            return "null";
-        }
-        if (value instanceof JsonString) {
-            return quote(((JsonString)value).getString());
-        }
-        if (value instanceof Number) {
-            return numberToString((Number) value);
-        }
-        if (value instanceof Boolean) {
-            return value.toString();
-        }
-        if (value instanceof JsonObject) {
-            return prettyPrint((JsonObject)value, opt);
-        }
-        if (value instanceof JsonArray) {
-            return prettyPrint((JsonArray)value, opt);
-        }
-        return quote(value.toString());
-
-    }
-
-    /**
-     * Produce a string from a Number.
-     * @param  n A Number
-     * @return A String.
-     * @throws JSONException If n is a non-finite number.
-     */
-    public String numberToString(Number n) {
-        if (n == null) {
-            throw new NullPointerException("Null pointer");
-        }
-        testNumberValidity(n);
-
-        // Shave off trailing zeros and decimal point, if possible.
-
-        String s = n.toString();
-        if (s.indexOf('.') > 0 && s.indexOf('e') < 0 && s.indexOf('E') < 0) {
-            while (s.endsWith("0")) {
-                s = s.substring(0, s.length() - 1);
-            }
-            if (s.endsWith(".")) {
-                s = s.substring(0, s.length() - 1);
-            }
-        }
-        return s;
-    }
-
-    /** Decide whether o must be skipped and added to a, when rendering a JSONObject */
-    private boolean skipChildObject(JsonArrayBuilder a, Options  opt, String key, Object value) {
-        if(opt.arraysForChildren && (value instanceof JsonObject)) {
-            JsonObjectBuilder builder = Json.createObjectBuilder();
-            builder.add(opt.childNameKey, key);
-            for (Map.Entry<String, JsonValue> entry : ((JsonObject) value).entrySet()) {
-                builder.add(entry.getKey(), entry.getValue());
-            }
-            a.add(builder);
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Make a prettyprinted JSON text of this JSONObject.
-     * <p>
-     * Warning: This method assumes that the data structure is acyclical.
-     * @return a printable, displayable, transmittable
-     *  representation of the object, beginning
-     *  with <code>{</code>&nbsp;<small>(left brace)</small> and ending
-     *  with <code>}</code>&nbsp;<small>(right brace)</small>.
-     * @throws IllegalArgumentException If the object contains an invalid number.
-     */
-    public String prettyPrint(JsonObject jo, Options opt) {
-        int n = jo.size();
-        if (n == 0) {
-            return "{}";
-        }
-        final JsonArrayBuilder children = Json.createArrayBuilder();
-        Iterator<String> keys = jo.keySet().iterator();
-        StringBuilder sb = new StringBuilder("{");
-        int newindent = opt.initialIndent + opt.indent;
-        String o;
-        if (n == 1) {
-            o = keys.next();
-            final Object v = jo.get(o);
-            if(!skipChildObject(children, opt, o, v)) {
-                sb.append(quote(o));
-                sb.append(": ");
-                sb.append(valueToString(v, opt));
-            }
-        } else {
-            while (keys.hasNext()) {
-                o = keys.next();
-                final Object v = jo.get(o);
-                if(skipChildObject(children, opt, o, v)) {
-                    continue;
-                }
-                if (sb.length() > 1) {
-                    sb.append(",\n");
-                } else {
-                    sb.append('\n');
-                }
-                indent(sb, newindent);
-                sb.append(quote(o.toString()));
-                sb.append(": ");
-                sb.append(valueToString(v,
-                        options().withIndent(opt.indent).withInitialIndent(newindent)));
-            }
-            if (sb.length() > 1) {
-                sb.append('\n');
-                indent(sb, newindent);
-            }
-        }
-
-        /** Render children if any were skipped (in "children in arrays" mode) */
-        JsonArray childrenArray = children.build();
-        if(childrenArray.size() > 0) {
-            if (sb.length() > 1) {
-                sb.append(",\n");
-            } else {
-                sb.append('\n');
-            }
-            final Options childOpt = new Options(opt);
-            childOpt.withInitialIndent(childOpt.initialIndent + newindent);
-            indent(sb, childOpt.initialIndent);
-            sb.append(quote(opt.childrenKey)).append(":");
-            sb.append(prettyPrint(childrenArray, childOpt));
-        }
-
-        sb.append('}');
-        return sb.toString();
-    }
-
-    /** Pretty-print a JSONArray */
-    public String prettyPrint(JsonArray ja, Options opt) {
-        int len = ja.size();
-        if (len == 0) {
-            return "[]";
-        }
-        int i;
-        StringBuilder sb = new StringBuilder("[");
-        if (len == 1) {
-            sb.append(valueToString(ja.get(0), opt));
-        } else {
-            final int newindent = opt.initialIndent + opt.indent;
-            if(opt.hasIndent()) {
-                sb.append('\n');
-            }
-            for (i = 0; i < len; i += 1) {
-                if (i > 0) {
-                    sb.append(',');
-                    if(opt.hasIndent()) {
-                        sb.append('\n');
-                    }
-                }
-                indent(sb, newindent);
-                sb.append(valueToString(ja.get(i), opt));
-            }
-            if(opt.hasIndent()) {
-                sb.append('\n');
-            }
-            indent(sb, opt.initialIndent);
-        }
-        sb.append(']');
-        return sb.toString();
-    }
-
-    /**
-     * Throw an exception if the object is an NaN or infinite number.
-     * @param o The object to test.
-     * @throws IllegalArgumentException If o is a non-finite number.
-     */
-    public void testNumberValidity(Object o) {
-        if (o != null) {
-            if (o instanceof Double) {
-                if (((Double)o).isInfinite() || ((Double)o).isNaN()) {
-                    throw new IllegalArgumentException(
-                        "JSON does not allow non-finite numbers");
-                }
-            } else if (o instanceof Float) {
-                if (((Float)o).isInfinite() || ((Float)o).isNaN()) {
-                    throw new IllegalArgumentException(
-                        "JSON does not allow non-finite numbers.");
-                }
-            }
-        }
-    }
-
-    /**
-     * Make a string from the contents of this JSONArray. The
-     * <code>separator</code> string is inserted between each element.
-     * Warning: This method assumes that the data structure is acyclical.
-     * @param separator A string that will be inserted between the elements.
-     * @return a string.
-     * @throws JSONException If the array contains an invalid number.
-     */
-    public String join(JsonArray ja, String separator) {
-        final int len = ja.size();
-        StringBuffer sb = new StringBuffer();
-
-        for (int i = 0; i < len; i += 1) {
-            if (i > 0) {
-                sb.append(separator);
-            }
-            sb.append(valueToString(ja.get(i)));
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Write the contents of the supplied JSONObject as JSON text to a writer.
-     * For compactness, no whitespace is added.
-     * <p>
-     * Warning: This method assumes that the data structure is acyclical.
-     *
-     * @return The writer.
-     * @throws IOException
-     */
-    public Writer write(Writer writer, JsonObject jo) throws IOException{
-       Json.createGenerator(writer).write(jo).flush();
-        
-       return writer;
-    }
-
-    /**
-     * Write the contents of the supplied JSONArray as JSON text to a writer.
-     * For compactness, no whitespace is added.
-     * <p>
-     * Warning: This method assumes that the data structure is acyclical.
-     *
-     * @return The writer.
-     * @throws IOException
-     */
-    public Writer write(Writer writer, JsonArray ja) throws IOException {
-        Json.createGenerator(writer).write(ja).flush();
-        return writer;
-    }
-
-    /**
-     * Produce a string from a double. The string "null" will be returned if
-     * the number is not finite.
-     * @param  d A double.
-     * @return A String.
-     */
-    public String doubleToString(double d) {
-        if (Double.isInfinite(d) || Double.isNaN(d)) {
-            return "null";
-        }
-
-        // Shave off trailing zeros and decimal point, if possible.
-
-        String s = Double.toString(d);
-        if (s.indexOf('.') > 0 && s.indexOf('e') < 0 && s.indexOf('E') < 0) {
-            while (s.endsWith("0")) {
-                s = s.substring(0, s.length() - 1);
-            }
-            if (s.endsWith(".")) {
-                s = s.substring(0, s.length() - 1);
-            }
-        }
-        return s;
-    }
-}
diff --git a/src/main/java/org/apache/sling/servlets/get/impl/util/JsonToText.java b/src/main/java/org/apache/sling/servlets/get/impl/util/JsonToText.java
new file mode 100644
index 0000000..c12dc42
--- /dev/null
+++ b/src/main/java/org/apache/sling/servlets/get/impl/util/JsonToText.java
@@ -0,0 +1,288 @@
+/*
+ * 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.servlets.get.impl.util;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonValue;
+
+public class JsonToText
+{
+    /** Rendering options */
+    static public class Options {
+        int indent;
+        private boolean indentIsPositive;
+        int initialIndent;
+        boolean arraysForChildren;
+
+        public static final String DEFAULT_CHILDREN_KEY = "__children__";
+        public static final String DEFAULT_CHILD_NAME_KEY = "__name__";
+
+        String childrenKey = DEFAULT_CHILDREN_KEY;
+        String childNameKey = DEFAULT_CHILD_NAME_KEY;
+
+        /** Clients use JSONRenderer.options() to create objects */
+        private Options() {
+        }
+
+        Options(Options opt) {
+            this.indent = opt.indent;
+            this.indentIsPositive = opt.indentIsPositive;
+            this.initialIndent = opt.initialIndent;
+            this.arraysForChildren = opt.arraysForChildren;
+        }
+
+        public Options withIndent(int n) {
+            indent = n;
+            indentIsPositive = indent > 0;
+            return this;
+        }
+
+        public Options withInitialIndent(int n) {
+            initialIndent = n;
+            return this;
+        }
+
+        public Options withArraysForChildren(boolean b) {
+            arraysForChildren = b;
+            return this;
+        }
+
+        public Options withChildNameKey(String key) {
+            childNameKey = key;
+            return this;
+        }
+
+        public Options withChildrenKey(String key) {
+            childrenKey = key;
+            return this;
+        }
+
+        boolean hasIndent() {
+            return indentIsPositive;
+        }
+    }
+
+    /** Return an Options object with default values */
+    public Options options() {
+        return new Options();
+    }
+
+    /** Write N spaces to sb for indentation */
+    private void indent(StringBuilder sb, int howMuch) {
+        for (int i=0; i < howMuch; i++) {
+            sb.append(' ');
+        }
+    }
+
+    /** Quote the supplied string for JSON */
+    private String quote(String string) {
+        if (string == null || string.length() == 0) {
+            return "\"\"";
+        }
+
+        char          b;
+        char          c = 0;
+        int           i;
+        int           len = string.length();
+        StringBuilder sb = new StringBuilder(len + 2);
+        String        t;
+
+        sb.append('"');
+        for (i = 0; i < len; i += 1) {
+            b = c;
+            c = string.charAt(i);
+            switch (c) {
+                case '\\':
+                case '"':
+                    sb.append('\\');
+                    sb.append(c);
+                    break;
+                case '/':
+                    if (b == '<') {
+                        sb.append('\\');
+                    }
+                    sb.append(c);
+                    break;
+                case '\b':
+                    sb.append("\\b");
+                    break;
+                case '\t':
+                    sb.append("\\t");
+                    break;
+                case '\n':
+                    sb.append("\\n");
+                    break;
+                case '\f':
+                    sb.append("\\f");
+                    break;
+                case '\r':
+                    sb.append("\\r");
+                    break;
+                default:
+                    if (c < ' ' || (c >= '\u0080' && c < '\u00a0') ||
+                            (c >= '\u2000' && c < '\u2100')) {
+                        t = "000" + Integer.toHexString(c);
+                        sb.append("\\u").append(t.substring(t.length() - 4));
+                    } else {
+                        sb.append(c);
+                    }
+            }
+        }
+        sb.append('"');
+        return sb.toString();
+    }
+
+
+
+    /** Make a JSON String of an Object value, with rendering options
+     */
+    private String valueToString(JsonValue value, Options opt) {
+        if (value instanceof JsonObject || value instanceof JsonArray) {
+            return prettyPrint((JsonArray)value, opt);
+        }
+        return value.toString();
+    }
+
+    /** Decide whether o must be skipped and added to a, when rendering a JSONObject */
+    private boolean skipChildObject(JsonArrayBuilder a, Options  opt, String key, Object value) {
+        if(opt.arraysForChildren && (value instanceof JsonObject)) {
+            JsonObjectBuilder builder = Json.createObjectBuilder();
+            builder.add(opt.childNameKey, key);
+            for (Map.Entry<String, JsonValue> entry : ((JsonObject) value).entrySet()) {
+                builder.add(entry.getKey(), entry.getValue());
+            }
+            a.add(builder);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Make a prettyprinted JSON text of this JSONObject.
+     * <p>
+     * Warning: This method assumes that the data structure is acyclical.
+     * @return a printable, displayable, transmittable
+     *  representation of the object, beginning
+     *  with <code>{</code>&nbsp;<small>(left brace)</small> and ending
+     *  with <code>}</code>&nbsp;<small>(right brace)</small>.
+     * @throws IllegalArgumentException If the object contains an invalid number.
+     */
+    public String prettyPrint(JsonObject jo, Options opt) {
+        int n = jo.size();
+        if (n == 0) {
+            return "{}";
+        }
+        final JsonArrayBuilder children = Json.createArrayBuilder();
+        Iterator<String> keys = jo.keySet().iterator();
+        StringBuilder sb = new StringBuilder("{");
+        int newindent = opt.initialIndent + opt.indent;
+        String o;
+        if (n == 1) {
+            o = keys.next();
+            final JsonValue v = jo.get(o);
+            if(!skipChildObject(children, opt, o, v)) {
+                sb.append(quote(o));
+                sb.append(": ");
+                sb.append(valueToString(v, opt));
+            }
+        } else {
+            while (keys.hasNext()) {
+                o = keys.next();
+                final JsonValue v = jo.get(o);
+                if(skipChildObject(children, opt, o, v)) {
+                    continue;
+                }
+                if (sb.length() > 1) {
+                    sb.append(",\n");
+                } else {
+                    sb.append('\n');
+                }
+                indent(sb, newindent);
+                sb.append(quote(o.toString()));
+                sb.append(": ");
+                sb.append(valueToString(v,
+                        options().withIndent(opt.indent).withInitialIndent(newindent)));
+            }
+            if (sb.length() > 1) {
+                sb.append('\n');
+                indent(sb, newindent);
+            }
+        }
+
+        /** Render children if any were skipped (in "children in arrays" mode) */
+        JsonArray childrenArray = children.build();
+        if(childrenArray.size() > 0) {
+            if (sb.length() > 1) {
+                sb.append(",\n");
+            } else {
+                sb.append('\n');
+            }
+            final Options childOpt = new Options(opt);
+            childOpt.withInitialIndent(childOpt.initialIndent + newindent);
+            indent(sb, childOpt.initialIndent);
+            sb.append(quote(opt.childrenKey)).append(":");
+            sb.append(prettyPrint(childrenArray, childOpt));
+        }
+
+        sb.append('}');
+        return sb.toString();
+    }
+
+    /** Pretty-print a JSONArray */
+    public String prettyPrint(JsonArray ja, Options opt) {
+        int len = ja.size();
+        if (len == 0) {
+            return "[]";
+        }
+        int i;
+        StringBuilder sb = new StringBuilder("[");
+        if (len == 1) {
+            sb.append(valueToString(ja.get(0), opt));
+        } else {
+            final int newindent = opt.initialIndent + opt.indent;
+            if(opt.hasIndent()) {
+                sb.append('\n');
+            }
+            for (i = 0; i < len; i += 1) {
+                if (i > 0) {
+                    sb.append(',');
+                    if(opt.hasIndent()) {
+                        sb.append('\n');
+                    }
+                }
+                indent(sb, newindent);
+                sb.append(valueToString(ja.get(i), opt));
+            }
+            if(opt.hasIndent()) {
+                sb.append('\n');
+            }
+            indent(sb, opt.initialIndent);
+        }
+        sb.append(']');
+        return sb.toString();
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/servlets/get/impl/util/ResourceTraversor.java b/src/main/java/org/apache/sling/servlets/get/impl/util/ResourceTraversor.java
index 6e913d6..c42df33 100644
--- a/src/main/java/org/apache/sling/servlets/get/impl/util/ResourceTraversor.java
+++ b/src/main/java/org/apache/sling/servlets/get/impl/util/ResourceTraversor.java
@@ -33,17 +33,7 @@
 
 public class ResourceTraversor
 {
-    public static final class Entry {
-        public final Resource resource;
-        public final JsonObjectBuilder json;
-
-        public Entry(final Resource r, final JsonObjectBuilder o) {
-            this.resource = r;
-            this.json = o;
-        }
-    }
-
-    Map<JsonObjectBuilder, List<Entry>> tree = new HashMap<>();
+    Map<Resource, List<Resource>> tree = new HashMap<>();
 
     private long count;
 
@@ -53,9 +43,9 @@
 
     private final JsonObjectBuilder startObject;
 
-    private LinkedList<Entry> currentQueue;
+    private LinkedList<Resource> currentQueue;
 
-    private LinkedList<Entry> nextQueue;
+    private LinkedList<Resource> nextQueue;
 
     private final Resource startResource;
 
@@ -81,12 +71,12 @@
      * nodes is reached on a "deep" traversal (where "deep" === level greater
      * than 1).
      *
-     * @return -1 if everything went fine, a positive valuew when the resource
+     * @return -1 if everything went fine, a positive value when the resource
      *            has more child nodes then allowed.
      * @throws JSONException
      */
     public int collectResources() throws RecursionTooDeepException {
-        return collectChildren(startResource, this.startObject, 0);
+        return collectChildren(startResource, 0);
     }
 
     /**
@@ -94,28 +84,26 @@
      * @param currentLevel
      * @throws JSONException
      */
-    private int collectChildren(final Resource resource,
-            final JsonObjectBuilder jsonObj,
-            int currentLevel) {
+    private int collectChildren(final Resource resource, int currentLevel) {
 
         if (maxRecursionLevels == -1 || currentLevel < maxRecursionLevels) {
             final Iterator<Resource> children = resource.listChildren();
+            List<Resource> childTree = tree.get(resource);
+            if (childTree == null)
+            {
+                childTree = new ArrayList<>();
+                tree.put(resource, childTree);
+            }
+            
             while (children.hasNext()) {
                 count++;
-                final Resource res = children.next();
+                final Resource child = children.next();
                 // SLING-2320: always allow enumeration of one's children;
                 // DOS-limitation is for deeper traversals.
                 if (count > maxResources && maxRecursionLevels != 1) {
                     return currentLevel;
                 }
-                Entry child = new Entry(res, adapt(res));
                 nextQueue.addLast(child);
-                List<Entry> childTree = tree.get(jsonObj);
-                if (childTree == null)
-                {
-                    childTree = new ArrayList<>();
-                    tree.put(jsonObj, childTree);
-                }
                 childTree.add(child);
             }
         }
@@ -131,8 +119,7 @@
                 currentQueue = nextQueue;
                 nextQueue = new LinkedList<>();
             }
-            final Entry nextResource = currentQueue.removeFirst();
-            final int maxLevel = collectChildren(nextResource.resource, nextResource.json, currentLevel);
+            final int maxLevel = collectChildren(currentQueue.removeFirst(), currentLevel);
             if ( maxLevel != -1 ) {
                 return maxLevel;
             }
@@ -151,27 +138,17 @@
         return JsonObjectCreator.create(resource);
     }
 
-    /**
-     * @return The number of resources this visitor found.
-     */
-    public long getCount() {
-        return count;
-    }
-
     public JsonObject getJSONObject() {
-
-        return addChildren(startObject).build();
+        return addChildren(startResource,startObject).build();
     }
 
-    private JsonObjectBuilder addChildren(JsonObjectBuilder builder) {
-        List<Entry> children = tree.get(builder);
-
+    private JsonObjectBuilder addChildren(Resource resource,JsonObjectBuilder builder) {
+    	List<Resource> children = tree.get(resource);
+    	
         if (children != null)
         {
-            for (Entry child : children) {
-                addChildren(child.json);
-
-                builder.add(child.resource.getName(), child.json);
+        	for (Resource child:children) {
+                builder.add(child.getName(), addChildren(child, adapt(child)));
             }
         }
 
diff --git a/src/test/java/org/apache/sling/servlets/get/impl/DefaultGetServletTest.java b/src/test/java/org/apache/sling/servlets/get/impl/DefaultGetServletTest.java
index acfbb28..7628bbe 100644
--- a/src/test/java/org/apache/sling/servlets/get/impl/DefaultGetServletTest.java
+++ b/src/test/java/org/apache/sling/servlets/get/impl/DefaultGetServletTest.java
@@ -25,6 +25,7 @@
 import java.util.Map;
 
 import javax.servlet.Servlet;
+import javax.servlet.ServletContext;
 
 import org.junit.Test;
 import org.mockito.Mockito;
@@ -32,7 +33,12 @@
 public class DefaultGetServletTest {
 
     @Test public void testDisabledAlias() throws Exception {
-        final DefaultGetServlet servlet = new DefaultGetServlet();
+        @SuppressWarnings("serial")
+		final DefaultGetServlet servlet = new DefaultGetServlet() {
+        	public ServletContext getServletContext() {
+        		return null;
+        	}
+        };
         final DefaultGetServlet.Config config = Mockito.mock(DefaultGetServlet.Config.class);
         Mockito.when(config.enable_html()).thenReturn(true);
         Mockito.when(config.enable_json()).thenReturn(true);
diff --git a/src/test/java/org/apache/sling/servlets/get/impl/JsonRendererServletTest.java b/src/test/java/org/apache/sling/servlets/get/impl/JsonRendererServletTest.java
index 01538bf..4ba8caa 100644
--- a/src/test/java/org/apache/sling/servlets/get/impl/JsonRendererServletTest.java
+++ b/src/test/java/org/apache/sling/servlets/get/impl/JsonRendererServletTest.java
@@ -24,7 +24,7 @@
 import org.apache.sling.commons.testing.sling.MockResourceResolver;
 import org.apache.sling.commons.testing.sling.MockSlingHttpServletRequest;
 import org.apache.sling.commons.testing.sling.MockSlingHttpServletResponse;
-import org.apache.sling.servlets.get.impl.helpers.JsonRendererServlet;
+import org.apache.sling.servlets.get.impl.helpers.JsonRenderer;
 
 import static org.junit.Assert.assertEquals;
 import junitx.util.PrivateAccessor;
@@ -79,7 +79,7 @@
 		request.setResource(resolver.getResource(path));
 
 		MockSlingHttpServletResponse response = new MockSlingHttpServletResponse();
-		JsonRendererServlet servlet = new JsonRendererServlet(1000);
+		JsonRenderer servlet = new JsonRenderer(1000);
 		PrivateAccessor.invoke(servlet, "doGet",
 				new Class[]{SlingHttpServletRequest.class, SlingHttpServletResponse.class},
 				new Object[]{request, response});
diff --git a/src/test/java/org/apache/sling/servlets/get/impl/helpers/HtmlRendererServletTest.java b/src/test/java/org/apache/sling/servlets/get/impl/helpers/HtmlRendererServletTest.java
index 5786f11..b7feaf8 100644
--- a/src/test/java/org/apache/sling/servlets/get/impl/helpers/HtmlRendererServletTest.java
+++ b/src/test/java/org/apache/sling/servlets/get/impl/helpers/HtmlRendererServletTest.java
@@ -64,9 +64,9 @@
     public void testEscaping() throws ServletException, IOException {
         XSSAPI xss = Mockito.mock(XSSAPI.class);
 
-        final HtmlRendererServlet servlet = new HtmlRendererServlet(xss);
+        final HtmlRenderer servlet = new HtmlRenderer(xss);
 
-        servlet.doGet(request, response);
+        servlet.render(request, response);
 
         Mockito.verify(xss).encodeForHTML("<script>alert(1);</script>");
     }
diff --git a/src/test/java/org/apache/sling/servlets/get/impl/helpers/JsonRendererServletTest.java b/src/test/java/org/apache/sling/servlets/get/impl/helpers/JsonRendererServletTest.java
index 859c6e7..b2c5cd3 100644
--- a/src/test/java/org/apache/sling/servlets/get/impl/helpers/JsonRendererServletTest.java
+++ b/src/test/java/org/apache/sling/servlets/get/impl/helpers/JsonRendererServletTest.java
@@ -40,7 +40,7 @@
     private SlingHttpServletRequest request;
     private SlingHttpServletResponse response;
     private String [] selectors;
-    private JsonRendererServlet jrs;
+    private JsonRenderer jrs;
     
     @Before
     public void setup() {
@@ -59,7 +59,7 @@
         
         response = Mockito.mock(SlingHttpServletResponse.class);
         
-        jrs = new JsonRendererServlet(42);
+        jrs = new JsonRenderer(42);
     }
     
     @Test
@@ -106,7 +106,7 @@
     @Test
     public void testBadRequest() throws IOException {
         selectors = new String[] { "bad", "selectors" };
-        jrs.doGet(request, response);
+        jrs.render(request, response);
         Mockito.verify(response, Mockito.times(1)).sendError(Matchers.anyInt(), Matchers.anyString());
     }
 }
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/servlets/get/impl/helpers/StreamRendererServletTest.java b/src/test/java/org/apache/sling/servlets/get/impl/helpers/StreamRendererServletTest.java
index b62c185..2423ecb 100644
--- a/src/test/java/org/apache/sling/servlets/get/impl/helpers/StreamRendererServletTest.java
+++ b/src/test/java/org/apache/sling/servlets/get/impl/helpers/StreamRendererServletTest.java
@@ -46,7 +46,7 @@
     public void testResultingLength() throws IOException {
         final ByteArrayInputStream in = new ByteArrayInputStream("12345678".getBytes());
         final ByteArrayOutputStream out = new ByteArrayOutputStream();
-        StreamRendererServlet.staticCopyRange(in, out, 2, 4);
+        StreamRenderer.staticCopyRange(in, out, 2, 4);
         final String result = out.toString();
         assertEquals(2, result.length());
         assertEquals("34", result);
@@ -54,11 +54,11 @@
     
     private void runTests(int randomSeed) throws IOException {
         final Random random = new Random(randomSeed);
-        assertCopyRange(random, StreamRendererServlet.IO_BUFFER_SIZE * 2 + 42);
-        assertCopyRange(random, StreamRendererServlet.IO_BUFFER_SIZE * 3);
-        assertCopyRange(random, StreamRendererServlet.IO_BUFFER_SIZE);
-        assertCopyRange(random, StreamRendererServlet.IO_BUFFER_SIZE - 1);
-        assertCopyRange(random, random.nextInt(StreamRendererServlet.IO_BUFFER_SIZE));
+        assertCopyRange(random, StreamRenderer.IO_BUFFER_SIZE * 2 + 42);
+        assertCopyRange(random, StreamRenderer.IO_BUFFER_SIZE * 3);
+        assertCopyRange(random, StreamRenderer.IO_BUFFER_SIZE);
+        assertCopyRange(random, StreamRenderer.IO_BUFFER_SIZE - 1);
+        assertCopyRange(random, random.nextInt(StreamRenderer.IO_BUFFER_SIZE));
         assertCopyRange(random, 42);
         assertCopyRange(random, 1);
     }
@@ -118,7 +118,7 @@
             byte[] expected, InputStream input, int a, int b) throws IOException {
         ByteArrayOutputStream output = new ByteArrayOutputStream();
 
-        StreamRendererServlet.staticCopyRange(input, output, a, b);
+        StreamRenderer.staticCopyRange(input, output, a, b);
 
         byte[] actual = output.toByteArray();
         assertEquals(b - a, actual.length);
@@ -136,12 +136,7 @@
         final ServletContext sc = Mockito.mock(ServletContext.class);
         
         @SuppressWarnings("serial")
-		StreamRendererServlet streamRendererServlet = new StreamRendererServlet(true,new String []{"/"}) {
-            @Override
-            public ServletContext getServletContext() {
-                return sc;
-            }
-        };        
+		StreamRenderer streamRendererServlet = new StreamRenderer(true,new String []{"/"},sc);       
 
         Mockito.when(resource.getResourceMetadata()).thenReturn(meta);
         PrivateAccessor.invoke(streamRendererServlet, "setHeaders", new Class[]{Resource.class, SlingHttpServletResponse.class}, new Object[]{resource, response});