incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fmesc...@apache.org
Subject svn commit: r591965 - in /incubator/sling/trunk/microsling/microsling-core/src: main/java/org/apache/sling/microsling/resource/MicroslingResourceResolver.java test/java/org/apache/sling/microsling/resource/MicroslingResourceResolverTest.java
Date Mon, 05 Nov 2007 11:45:03 GMT
Author: fmeschbe
Date: Mon Nov  5 03:44:37 2007
New Revision: 591965

URL: http://svn.apache.org/viewvc?rev=591965&view=rev
Log:
SLING-88 Add missing implementations for listChildren and getResource methods and
some unit tests for the relative path segment (. and ..) resolution

Added:
    incubator/sling/trunk/microsling/microsling-core/src/test/java/org/apache/sling/microsling/resource/MicroslingResourceResolverTest.java
Modified:
    incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/resource/MicroslingResourceResolver.java

Modified: incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/resource/MicroslingResourceResolver.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/resource/MicroslingResourceResolver.java?rev=591965&r1=591964&r2=591965&view=diff
==============================================================================
--- incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/resource/MicroslingResourceResolver.java
(original)
+++ incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/resource/MicroslingResourceResolver.java
Mon Nov  5 03:44:37 2007
@@ -18,10 +18,13 @@
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 
+import javax.jcr.Node;
 import javax.jcr.NodeIterator;
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
@@ -58,18 +61,9 @@
         this.session = session;
     }
 
-    public void dispose() {
-        if (session != null) {
-            try {
-                session.logout();
-            } catch (Throwable t) {
-                log.warn("dispose: Unexpected problem logging out", t);
-            }
-
-            session = null;
-        }
-    }
-
+    /**
+     * Resolves the Resource from the request
+     */
     public Resource resolve(ServletRequest request) throws SlingException,
             ResourceNotFoundException {
         Resource result = null;
@@ -79,12 +73,7 @@
             Session session = getSession();
             final ResourcePathIterator it = new ResourcePathIterator(pathInfo);
             while (it.hasNext() && result == null) {
-                path = it.next();
-                if (log.isDebugEnabled()) {
-                    log.debug("Trying to locate Resource at path '" + path
-                        + "'");
-                }
-                result = getResource(session, path);
+                result = getResource(session, it.next());
             }
         } catch (RepositoryException re) {
             throw new SlingException("RepositoryException for path=" + path, re);
@@ -97,32 +86,82 @@
         return result;
     }
 
+    /**
+     * Resolves a resource relative to the given base resource
+     */
     public Resource getResource(Resource base, String path)
             throws SlingException {
-        // TODO Auto-generated method stub
-        return null;
+
+        if (!path.startsWith("/")) {
+            path = base.getURI() + "/" + path;
+        }
+
+        return getResource(path);
     }
 
+    /**
+     * Resolves a resource with an absolute path
+     */
     public Resource getResource(String path) throws SlingException {
-        try {
-            Session session = getSession();
-            if (session.itemExists(path)) {
-                return getResource(session, path);
-            }
 
-            log.info("Path '{}' does not resolve to an Item", path);
-            return null;
-        } catch (RepositoryException re) {
-            throw new SlingException("Cannot get resource " + path, re);
+        path = resolveRelativeSegments(path);
+        if (path != null) {
+            try {
+                return getResource(getSession(), path);
+            } catch (RepositoryException re) {
+                throw new SlingException("Cannot get resource " + path, re);
+            }
         }
+
+        // relative path segments cannot be resolved
+        return null;
     }
 
-    public Iterator<Resource> listChildren(Resource parent)
+    /**
+     * Find all child resources of the given parent resource
+     */
+    public Iterator<Resource> listChildren(final Resource parent)
             throws SlingException {
-        // TODO Auto-generated method stub
-        return null;
+        if (parent.getRawData() instanceof Node) {
+
+            try {
+                final NodeIterator children = ((Node) parent.getRawData()).getNodes();
+                return new Iterator<Resource>() {
+
+                    public boolean hasNext() {
+                        return children.hasNext();
+                    }
+
+                    public Resource next() {
+                        try {
+                            return new JcrNodeResource(children.nextNode());
+                        } catch (RepositoryException re) {
+                            log.warn(
+                                "Problem while trying to create a resource", re);
+                            return new NonExistingResource(parent.getURI()
+                                + "/?");
+                        }
+                    }
+
+                    public void remove() {
+                        throw new UnsupportedOperationException("remove");
+                    }
+
+                };
+            } catch (RepositoryException re) {
+                throw new SlingException("Cannot get children of Resource "
+                    + parent, re);
+            }
+        }
+
+        // return an empty iterator if parent has no node
+        List<Resource> empty = Collections.emptyList();
+        return empty.iterator();
     }
 
+    /**
+     * Query the JCR repository and return an iterator of query results
+     */
     public Iterator<Map<String, Object>> queryResources(String query,
             String language) throws SlingException {
         try {
@@ -156,6 +195,9 @@
         }
     }
 
+    /**
+     * Find all resources matching the given query
+     */
     public Iterator<Resource> findResources(String query, String language)
             throws SlingException {
         try {
@@ -183,6 +225,7 @@
         }
     }
 
+    /** Returns the session used by this resolver */
     protected Session getSession() throws SlingException {
         if (session != null && session.isLive()) {
             return session;
@@ -191,6 +234,7 @@
         throw new SlingException("Session has already been closed");
     }
 
+    /** Creates a JcrNodeResource with the given path if existing */
     protected Resource getResource(Session session, String path)
             throws RepositoryException {
         if (session.itemExists(path)) {
@@ -201,9 +245,86 @@
             return result;
         }
 
+        log.info("Path '{}' does not resolve to an Item", path);
         return null;
     }
 
+    /**
+     * Resolves relative path segments '.' and '..' in the absolute path.
+     * Returns null if not possible (.. points above root) or if path is not
+     * absolute.
+     */
+    protected String resolveRelativeSegments(String path) {
+
+        // require non-empty absolute path !
+        if (path.length() == 0 || path.charAt(0) != '/') {
+            log.error("resolveRelativeSegments: Path '{}' must be absolute", path);
+            return null;
+        }
+
+        // prepare the path buffer with trailing slash (simplifies impl)
+        char[] buf = new char[path.length() + 1];
+        path.getChars(0, path.length(), buf, 0);
+        buf[buf.length - 1] = '/';
+
+        int lastSlash = 0; // last slash in path
+        int numDots = 0; // number of consecutive dots after last slash
+
+        int bufPos = 0;
+        for (int bufIdx = lastSlash; bufIdx < buf.length; bufIdx++) {
+            char c = buf[bufIdx];
+            if (c == '/') {
+                if (numDots == 2) {
+                    if (bufPos == 0) {
+                        log.error("resolveRelativeSegments: Path '{}' cannot be resolved",
path);
+                        return null;
+                    }
+
+                    do {
+                        bufPos--;
+                    } while (bufPos > 0 && buf[bufPos] != '/');
+                }
+
+                lastSlash = bufIdx;
+                numDots = 0;
+            } else if (c == '.' && numDots < 2) {
+                numDots++;
+            } else {
+                // find the next slash
+                int nextSlash = bufIdx + 1;
+                while (nextSlash < buf.length && buf[nextSlash] != '/') {
+                    nextSlash++;
+                }
+
+                // append up to the next slash (or end of path)
+                if (bufPos < lastSlash) {
+                    int segLen = nextSlash - bufIdx + 1;
+                    System.arraycopy(buf, lastSlash, buf, bufPos, segLen);
+                    bufPos += segLen;
+                } else {
+                    bufPos = nextSlash;
+                }
+
+                numDots = 0;
+                lastSlash = nextSlash;
+                bufIdx = nextSlash;
+            }
+        }
+
+        if (bufPos == 0 && numDots == 0) {
+            log.debug("resolveRelativeSegments: Resolving '{}' to '/'", path);
+            return "/";
+        } else if (bufPos == path.length()) {
+            log.debug("resolveRelativeSegments: No resolution for '{}' needed", path);
+            return path;
+        }
+
+        String resolved = new String(buf, 0, bufPos);
+        log.debug("resolveRelativeSegments: Resolving '{}' to '{}'", path, resolved);
+        return resolved;
+    }
+
+    /** Helper method to execute a JCR query */
     private QueryResult queryInternal(String query, String language)
             throws RepositoryException, SlingException {
         Session s = getSession();
@@ -212,6 +333,7 @@
         return q.execute();
     }
 
+    /** Converts a JCR Value to a corresponding Java Object */
     private Object toJavaObject(Value value) throws RepositoryException {
         switch (value.getType()) {
             case PropertyType.BINARY:
@@ -234,6 +356,10 @@
         }
     }
 
+    /**
+     * Lazily acquired InputStream which only accesses the JCR Value InputStream
+     * if data is to be read from the stream.
+     */
     private static class LazyInputStream extends InputStream {
 
         private final Value value;
@@ -292,7 +418,7 @@
             try {
                 return getStream().markSupported();
             } catch (IOException ioe) {
-                // TODO: log
+                // ignore
             }
             return false;
         }
@@ -302,7 +428,7 @@
             try {
                 getStream().mark(readlimit);
             } catch (IOException ioe) {
-                // TODO: log
+                // ignore
             }
         }
 

Added: incubator/sling/trunk/microsling/microsling-core/src/test/java/org/apache/sling/microsling/resource/MicroslingResourceResolverTest.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/microsling/microsling-core/src/test/java/org/apache/sling/microsling/resource/MicroslingResourceResolverTest.java?rev=591965&view=auto
==============================================================================
--- incubator/sling/trunk/microsling/microsling-core/src/test/java/org/apache/sling/microsling/resource/MicroslingResourceResolverTest.java
(added)
+++ incubator/sling/trunk/microsling/microsling-core/src/test/java/org/apache/sling/microsling/resource/MicroslingResourceResolverTest.java
Mon Nov  5 03:44:37 2007
@@ -0,0 +1,132 @@
+/*
+ * 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.microsling.resource;
+
+import java.io.PrintWriter;
+
+import org.apache.log4j.ConsoleAppender;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.SimpleLayout;
+
+import junit.framework.TestCase;
+
+public class MicroslingResourceResolverTest extends TestCase {
+
+    private MicroslingResourceResolver resolver;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        LogManager.resetConfiguration();
+        ConsoleAppender ca = new ConsoleAppender();
+        ca.setWriter(new PrintWriter(System.out, true));
+        ca.setName("console");
+        ca.setLayout(new SimpleLayout());
+        ca.activateOptions();
+        LogManager.getRootLogger().addAppender(ca);
+
+        // may call with null, don't need repository for now
+        resolver = new MicroslingResourceResolver(null);
+    }
+
+    public void testResolveRelativeSegments() {
+
+        assertEquals("/", resolver.resolveRelativeSegments("/"));
+        assertEquals("/", resolver.resolveRelativeSegments("///"));
+
+        assertEquals("/a/b/c", resolver.resolveRelativeSegments("/a//b/c"));
+        assertEquals("/a/b/c", resolver.resolveRelativeSegments("/a/b//c"));
+        assertEquals("/a/b/c", resolver.resolveRelativeSegments("/a///b///c"));
+        assertEquals("/a/b/c", resolver.resolveRelativeSegments("/a/b/c/"));
+        assertEquals("/a/b/c", resolver.resolveRelativeSegments("/a/b/c//"));
+        assertEquals("/a/b/c", resolver.resolveRelativeSegments("/a/b/c///"));
+
+        assertEquals("/az/bz/cz", resolver.resolveRelativeSegments("/az//bz/cz"));
+        assertEquals("/az/bz/cz", resolver.resolveRelativeSegments("/az/bz//cz"));
+        assertEquals("/az/bz/cz", resolver.resolveRelativeSegments("/az///bz///cz"));
+        assertEquals("/az/bz/cz", resolver.resolveRelativeSegments("/az/bz/cz/"));
+        assertEquals("/az/bz/cz", resolver.resolveRelativeSegments("/az/bz/cz//"));
+        assertEquals("/az/bz/cz", resolver.resolveRelativeSegments("/az/bz/cz///"));
+
+        assertEquals("/a", resolver.resolveRelativeSegments("/a"));
+        assertEquals("/a", resolver.resolveRelativeSegments("//a"));
+        assertEquals("/a", resolver.resolveRelativeSegments("///a"));
+
+        assertEquals("/az", resolver.resolveRelativeSegments("/az"));
+        assertEquals("/az", resolver.resolveRelativeSegments("//az"));
+        assertEquals("/az", resolver.resolveRelativeSegments("///az"));
+
+        assertEquals("/", resolver.resolveRelativeSegments("/."));
+        assertEquals("/a", resolver.resolveRelativeSegments("/a/."));
+        assertEquals("/a", resolver.resolveRelativeSegments("/./a"));
+        assertEquals("/a/b", resolver.resolveRelativeSegments("/a/./b"));
+        assertEquals("/a/b", resolver.resolveRelativeSegments("/a/b/."));
+        assertEquals("/a/b", resolver.resolveRelativeSegments("/a/./b/."));
+
+        assertEquals("/", resolver.resolveRelativeSegments("/."));
+        assertEquals("/az", resolver.resolveRelativeSegments("/az/."));
+        assertEquals("/az", resolver.resolveRelativeSegments("/./az"));
+        assertEquals("/az/bz", resolver.resolveRelativeSegments("/az/./bz"));
+        assertEquals("/az/bz", resolver.resolveRelativeSegments("/az/bz/."));
+        assertEquals("/az/bz", resolver.resolveRelativeSegments("/az/./bz/."));
+
+        assertNull(resolver.resolveRelativeSegments("/.."));
+        assertNull(resolver.resolveRelativeSegments("/.."));
+        assertEquals("/", resolver.resolveRelativeSegments("/a/.."));
+        assertEquals("/a", resolver.resolveRelativeSegments("/a/b/.."));
+        assertEquals("/", resolver.resolveRelativeSegments("/a/b/../.."));
+        assertNull(resolver.resolveRelativeSegments("/a/b/../../.."));
+
+        assertNull(resolver.resolveRelativeSegments("/.."));
+        assertNull(resolver.resolveRelativeSegments("/.."));
+        assertEquals("/", resolver.resolveRelativeSegments("/az/.."));
+        assertEquals("/az", resolver.resolveRelativeSegments("/az/bz/.."));
+        assertEquals("/", resolver.resolveRelativeSegments("/az/bz/../.."));
+        assertNull(resolver.resolveRelativeSegments("/az/bz/../../.."));
+
+        assertEquals("/b", resolver.resolveRelativeSegments("/a/../b"));
+        assertEquals("/a/c", resolver.resolveRelativeSegments("/a/b/../c"));
+        assertEquals("/c", resolver.resolveRelativeSegments("/a/b/../../c"));
+        assertNull(resolver.resolveRelativeSegments("/a/b/../../../c"));
+
+        assertEquals("/bz", resolver.resolveRelativeSegments("/az/../bz"));
+        assertEquals("/az/cz", resolver.resolveRelativeSegments("/az/bz/../cz"));
+        assertEquals("/cz", resolver.resolveRelativeSegments("/az/bz/../../cz"));
+        assertNull(resolver.resolveRelativeSegments("/az/bz/../../../cz"));
+
+        assertEquals("/...", resolver.resolveRelativeSegments("/..."));
+        assertEquals("/a/...", resolver.resolveRelativeSegments("/a/..."));
+        assertEquals("/a/b/...", resolver.resolveRelativeSegments("/a/b/..."));
+
+        assertEquals("/az/...", resolver.resolveRelativeSegments("/az/..."));
+        assertEquals("/az/bz/...", resolver.resolveRelativeSegments("/az/bz/..."));
+
+        assertNull(resolver.resolveRelativeSegments("a/b/c"));
+        assertNull(resolver.resolveRelativeSegments("az/bz/cz"));
+        assertNull(resolver.resolveRelativeSegments(""));
+
+        try {
+            resolver.resolveRelativeSegments(null);
+            fail("Resolving null expects NullPointerException");
+        } catch (NullPointerException npe) {
+            // expected
+        }
+    }
+}



Mime
View raw message