You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ie...@apache.org on 2017/10/19 11:42:08 UTC

svn commit: r1812621 - in /sling/trunk: bundles/api/src/main/java/org/apache/sling/api/resource/ bundles/jcr/resource/ bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/ bundles/jcr/resource/src/main/java/org/apache/sling/jcr/re...

Author: ieb
Date: Thu Oct 19 11:42:07 2017
New Revision: 1812621

URL: http://svn.apache.org/viewvc?rev=1812621&view=rev
Log:
SLING-7140 Support redirects to URLs provided by the underlying resource provider.


Added:
    sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ExternalizableInputStream.java
    sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/URIProvider.java
    sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrExternalizableInputStream.java
Modified:
    sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/package-info.java
    sling/trunk/bundles/jcr/resource/pom.xml
    sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/HelperData.java
    sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java
    sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrProviderStateFactory.java
    sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProvider.java
    sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrModifiableValueMapTest.java
    sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/JcrNodeResourceIteratorTest.java
    sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceFactoryTest.java
    sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceTest.java
    sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrTestNodeResource.java
    sling/trunk/bundles/servlets/get/pom.xml
    sling/trunk/bundles/servlets/get/src/main/java/org/apache/sling/servlets/get/impl/helpers/StreamRendererServlet.java
    sling/trunk/launchpad/builder/src/main/provisioning/sling.txt

Added: sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ExternalizableInputStream.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ExternalizableInputStream.java?rev=1812621&view=auto
==============================================================================
--- sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ExternalizableInputStream.java (added)
+++ sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ExternalizableInputStream.java Thu Oct 19 11:42:07 2017
@@ -0,0 +1,49 @@
+/*
+ * 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.api.resource;
+
+import java.net.URI;
+
+/**
+ * This interface is normally used to extend an InputStream to indicate that it has a URI form that could
+ * be used in place of the InputStream if desired. It is used in situations where the internal of a ResourceProvider
+ * wants to offload IO to channels that do not pass through the JVM. The URI that is returned may have restrictions
+ * imposed on it requiring it to be used immediately. Do not store the URI for later usage as it will, in most cases,
+ * have expired.
+ *
+ * @since 2.11.0
+ */
+public interface ExternalizableInputStream {
+
+    /**
+     * Get a URI that is specific to the current session, and may be used anywhere. May return null if this
+     * type of URI is not available.
+     * @return a URI intended for any network context.
+     */
+    URI getURI();
+
+    /**
+     * Get a URI that is specific to the current session and may only be used in a private context. A private network context means
+     * that the URI may only be resolvable inside a private network. Usign this URL in any context will not always work, and
+     * may leak information about the private network.
+     * @return a URI intended for a private network context.
+     */
+    URI getPrivateURI();
+}

Added: sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/URIProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/URIProvider.java?rev=1812621&view=auto
==============================================================================
--- sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/URIProvider.java (added)
+++ sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/URIProvider.java Thu Oct 19 11:42:07 2017
@@ -0,0 +1,51 @@
+/*
+ * 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.api.resource;
+
+import org.osgi.annotation.versioning.ProviderType;
+
+import java.net.URI;
+
+/**
+ * Provides a URI in exchange for a Resource.
+ * Typically the Resource will represent something where is a URI is valiable and usefull.
+ * Implementations of this interface must ensure that the any underlying security model is delegated
+ * securely and not circumvented. Typically resource provider bundles should implement this provider as in most cases
+ * internal implementation details of the resource will be required to achieve the implementation. Ideally
+ * implementations should be carefully reviewed by peers.
+ *
+ * @since 2.11.0
+ */
+@ProviderType
+public interface URIProvider {
+
+    /**
+     * Return a URI appicable to the defined scope.
+     * @param scope the required scope.
+     * @param resource the resource to convert from.
+     * @return a URI if the resoruce has a URI suitable for the requested scope.
+     */
+    URI toURI(URIProvider.Scope scope, Resource resource);
+
+    enum Scope {
+        PUBLIC,
+        INTERNAL
+    }
+}
\ No newline at end of file

Modified: sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/package-info.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/package-info.java?rev=1812621&r1=1812620&r2=1812621&view=diff
==============================================================================
--- sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/package-info.java (original)
+++ sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/package-info.java Thu Oct 19 11:42:07 2017
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-@Version("2.10.1")
+@Version("2.11.0")
 package org.apache.sling.api.resource;
 
 import org.osgi.annotation.versioning.Version;

Modified: sling/trunk/bundles/jcr/resource/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/pom.xml?rev=1812621&r1=1812620&r2=1812621&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/pom.xml (original)
+++ sling/trunk/bundles/jcr/resource/pom.xml Thu Oct 19 11:42:07 2017
@@ -230,6 +230,11 @@
             <version>1.4</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.api</artifactId>
+            <version>2.16.3-SNAPSHOT</version>
+        </dependency>
     </dependencies>
 </project>
 

Modified: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/HelperData.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/HelperData.java?rev=1812621&r1=1812620&r2=1812621&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/HelperData.java (original)
+++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/HelperData.java Thu Oct 19 11:42:07 2017
@@ -23,6 +23,7 @@ import java.util.concurrent.atomic.Atomi
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 
+import org.apache.sling.api.resource.URIProvider;
 import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
 
 /**
@@ -31,12 +32,16 @@ import org.apache.sling.commons.classloa
  */
 public class HelperData {
 
+    private static final URIProvider[] EMPTY_URLPROVIDERS = new URIProvider[0];
+
     private final AtomicReference<DynamicClassLoaderManager> dynamicClassLoaderManagerReference;
+    private final AtomicReference<URIProvider[]> uriProviderReference;
 
     private volatile String[] namespacePrefixes;
 
-    public HelperData(final AtomicReference<DynamicClassLoaderManager> dynamicClassLoaderManagerReference) {
+    public HelperData(final AtomicReference<DynamicClassLoaderManager> dynamicClassLoaderManagerReference, AtomicReference<URIProvider[]> uriProviderReference) {
         this.dynamicClassLoaderManagerReference = dynamicClassLoaderManagerReference;
+        this.uriProviderReference = uriProviderReference;
     }
 
     public String[] getNamespacePrefixes(final Session session)
@@ -54,4 +59,12 @@ public class HelperData {
         }
         return dclm.getDynamicClassLoader();
     }
+
+    public URIProvider[] getURIProviders() {
+        URIProvider[] ups = this.uriProviderReference.get();
+        if ( ups == null) {
+            ups = EMPTY_URLPROVIDERS;
+        }
+        return ups;
+    }
 }

Added: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrExternalizableInputStream.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrExternalizableInputStream.java?rev=1812621&view=auto
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrExternalizableInputStream.java (added)
+++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrExternalizableInputStream.java Thu Oct 19 11:42:07 2017
@@ -0,0 +1,84 @@
+/*
+ * 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.jcr.resource.internal.helper.jcr;
+
+
+import org.apache.sling.api.resource.ExternalizableInputStream;
+
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+
+/**
+ * A lazy initialised input stream wrapping a JCR Property that also has a Public URI representation. The
+ * InputStream will be initialised when the first byte is read from the input stream so that the URI
+ * can be used without consuming any local IO resources.
+ *
+ * If a non any other form of URI is require, (ie Internal) then the URIProvider should be used directly. This
+ * class is written intentionally to *only* support public URIs.
+ */
+public class JcrExternalizableInputStream extends InputStream implements ExternalizableInputStream {
+    private final Property data;
+    private final URI uri;
+    private InputStream inputStream;
+
+
+    /**
+     * Construct the InputStream wrapping this existing stream and
+     * using a public URI
+     * @param data the binary JCR property.
+     * @param uri a public URI.
+     */
+    JcrExternalizableInputStream(Property data, URI uri) {
+        this.data = data;
+        this.uri = uri;
+    }
+
+    @Override
+    public int read() throws IOException {
+        return getInputStream().read();
+    }
+
+    private InputStream getInputStream() throws IOException {
+        if ( inputStream == null) {
+            try {
+                // perform lazy initialisation so that a consumer of
+                // this object can use the getURI method without triggering
+                // local IO operations. A DataSource implementation that
+                // converts the JCR Property to an InputStream might make a local
+                // copy. This avoids that IO operation.
+                inputStream = data.getBinary().getStream();
+            } catch (RepositoryException e) {
+                throw new IOException(e.getMessage(), e);
+            }
+        }
+        return inputStream;
+    }
+
+    @Override
+    public URI getURI() {
+        return uri;
+    }
+
+    @Override
+    public URI getPrivateURI() {
+        return null;
+    }
+}

Modified: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java?rev=1812621&r1=1812620&r2=1812621&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java (original)
+++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java Thu Oct 19 11:42:07 2017
@@ -22,6 +22,7 @@ import static org.apache.jackrabbit.JcrC
 import static org.apache.jackrabbit.JcrConstants.NT_LINKEDFILE;
 
 import java.io.InputStream;
+import java.net.URI;
 import java.security.AccessControlException;
 import java.util.Iterator;
 import java.util.Map;
@@ -31,12 +32,15 @@ import javax.jcr.ItemNotFoundException;
 import javax.jcr.Node;
 import javax.jcr.Property;
 import javax.jcr.RepositoryException;
+import javax.jcr.Value;
 
 import org.apache.sling.adapter.annotations.Adaptable;
 import org.apache.sling.adapter.annotations.Adapter;
+import org.apache.sling.api.resource.ExternalizableInputStream;
 import org.apache.sling.api.resource.ModifiableValueMap;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.URIProvider;
 import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.jcr.resource.api.JcrResourceConstants;
 import org.apache.sling.jcr.resource.internal.HelperData;
@@ -48,7 +52,8 @@ import org.slf4j.LoggerFactory;
 /** A Resource that wraps a JCR Node */
 @Adaptable(adaptableClass=Resource.class, adapters={
         @Adapter({Node.class, Map.class, Item.class, ValueMap.class}),
-        @Adapter(value=InputStream.class, condition="If the resource is a JcrNodeResource and has a jcr:data property or is an nt:file node.")
+        @Adapter(value=InputStream.class, condition="If the resource is a JcrNodeResource and has a jcr:data property or is an nt:file node."),
+        @Adapter(value=ExternalizableInputStream.class, condition="If the resource is a JcrNodeResource and has a jcr:data property or is an nt:file node, and can be read using a secure URL.")
 })
 class JcrNodeResource extends JcrItemResource<Node> { // this should be package private, see SLING-1414
 
@@ -201,7 +206,10 @@ class JcrNodeResource extends JcrItemRes
                         data = null;
                     }
                 }
-
+                URI uri =  convertToPublicURI();
+                if ( uri != null ) {
+                    return new JcrExternalizableInputStream(data, uri);
+                }
                 if (data != null) {
                     return data.getBinary().getStream();
                 }
@@ -216,6 +224,22 @@ class JcrNodeResource extends JcrItemRes
         return null;
     }
 
+    /**
+     * Ask each URIProvider in turn for a Public URI, and return the first
+     * public URI provided.
+     * @return a public URI.
+     */
+    private URI convertToPublicURI() {
+        for (URIProvider up : helper.getURIProviders()) {
+            URI u = up.toURI(URIProvider.Scope.PUBLIC, this);
+            if ( u != null) {
+                return u;
+            }
+        }
+        return null;
+    }
+
+
     // ---------- Descendable interface ----------------------------------------
 
     @Override

Modified: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrProviderStateFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrProviderStateFactory.java?rev=1812621&r1=1812620&r2=1812621&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrProviderStateFactory.java (original)
+++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrProviderStateFactory.java Thu Oct 19 11:42:07 2017
@@ -35,6 +35,7 @@ import javax.jcr.SimpleCredentials;
 import org.apache.sling.api.resource.LoginException;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.api.resource.URIProvider;
 import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
 import org.apache.sling.jcr.api.SlingRepository;
 import org.apache.sling.jcr.resource.api.JcrResourceConstants;
@@ -55,13 +56,16 @@ public class JcrProviderStateFactory {
     private final SlingRepository repository;
 
     private final AtomicReference<DynamicClassLoaderManager> dynamicClassLoaderManagerReference;
+    private final AtomicReference<URIProvider[]> uriProviderReference;
 
     public JcrProviderStateFactory(final ServiceReference<SlingRepository> repositoryReference,
             final SlingRepository repository,
-            final AtomicReference<DynamicClassLoaderManager> dynamicClassLoaderManagerReference) {
+            final AtomicReference<DynamicClassLoaderManager> dynamicClassLoaderManagerReference,
+                                   final AtomicReference<URIProvider[]> uriProviderReference) {
         this.repository = repository;
         this.repositoryReference = repositoryReference;
         this.dynamicClassLoaderManagerReference = dynamicClassLoaderManagerReference;
+        this.uriProviderReference = uriProviderReference;
     }
 
     /** Get the calling Bundle from auth info, fail if not provided
@@ -142,7 +146,7 @@ public class JcrProviderStateFactory {
             @Nullable final BundleContext ctx
     ) throws LoginException {
         final Session session = handleImpersonation(s, authenticationInfo, logoutSession);
-        final HelperData data = new HelperData(this.dynamicClassLoaderManagerReference);
+        final HelperData data = new HelperData(this.dynamicClassLoaderManagerReference, this.uriProviderReference);
         return new JcrProviderState(session, data, logoutSession, ctx, ctx == null ? null : repositoryReference);
     }
 

Modified: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProvider.java?rev=1812621&r1=1812620&r2=1812621&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProvider.java (original)
+++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProvider.java Thu Oct 19 11:42:07 2017
@@ -27,6 +27,7 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicReference;
 
 import javax.annotation.CheckForNull;
@@ -46,6 +47,7 @@ import org.apache.sling.api.resource.Per
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolverFactory;
 import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.api.resource.URIProvider;
 import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
 import org.apache.sling.jcr.api.SlingRepository;
 import org.apache.sling.jcr.resource.api.JcrResourceConstants;
@@ -107,12 +109,16 @@ public class JcrResourceProvider extends
     /** The JCR observation listeners. */
     private final Map<ObserverConfiguration, Closeable> listeners = new HashMap<>();
 
+    private final Map<URIProvider, URIProvider> providers = new ConcurrentHashMap<URIProvider, URIProvider>();
+
     private volatile SlingRepository repository;
 
     private volatile JcrProviderStateFactory stateFactory;
 
     private final AtomicReference<DynamicClassLoaderManager> classLoaderManagerReference = new AtomicReference<DynamicClassLoaderManager>();
 
+    private AtomicReference<URIProvider[]> uriProviderReference = new AtomicReference<URIProvider[]>();
+
     @Activate
     protected void activate(final ComponentContext context) throws RepositoryException {
         SlingRepository repository = context.locateService(REPOSITORY_REFERNENCE_NAME,
@@ -128,7 +134,7 @@ public class JcrResourceProvider extends
         this.repository = repository;
 
         this.stateFactory = new JcrProviderStateFactory(repositoryReference, repository,
-                classLoaderManagerReference);
+                classLoaderManagerReference, uriProviderReference);
     }
 
     @Deactivate
@@ -147,6 +153,29 @@ public class JcrResourceProvider extends
         this.classLoaderManagerReference.compareAndSet(dynamicClassLoaderManager, null);
     }
 
+    @Reference(
+            name = "uriprovider",
+            service = URIProvider.class,
+            cardinality = ReferenceCardinality.MULTIPLE,
+            policy = ReferencePolicy.DYNAMIC,
+            bind = "bindUriProvider",
+            unbind = "unbindUriProvider"
+    )
+    private void bindUriProvider(URIProvider uriProvider) {
+
+        providers.put(uriProvider, uriProvider);
+        updateURIProviders();
+    }
+    private void unbindUriProvider(URIProvider uriProvider) {
+        providers.remove(uriProvider);
+        updateURIProviders();
+    }
+
+    private void updateURIProviders() {
+        URIProvider[] ups = providers.values().toArray(new URIProvider[providers.size()]);
+        this.uriProviderReference.set(ups);
+    }
+
     @Override
     public void start(final ProviderContext ctx) {
         super.start(ctx);

Modified: sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrModifiableValueMapTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrModifiableValueMapTest.java?rev=1812621&r1=1812620&r2=1812621&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrModifiableValueMapTest.java (original)
+++ sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrModifiableValueMapTest.java Thu Oct 19 11:42:07 2017
@@ -45,6 +45,7 @@ import javax.jcr.nodetype.NodeType;
 import org.apache.commons.io.IOUtils;
 import org.apache.jackrabbit.util.Text;
 import org.apache.sling.api.resource.ModifiableValueMap;
+import org.apache.sling.api.resource.URIProvider;
 import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
 import org.apache.sling.commons.testing.jcr.RepositoryTestBase;
@@ -131,7 +132,7 @@ public class JcrModifiableValueMapTest e
     }
 
     private HelperData getHelperData() throws Exception {
-        return new HelperData(new AtomicReference<DynamicClassLoaderManager>());
+        return new HelperData(new AtomicReference<DynamicClassLoaderManager>(), new AtomicReference<URIProvider[]>());
     }
 
     private Map<String, Object> initialSet() {

Modified: sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/JcrNodeResourceIteratorTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/JcrNodeResourceIteratorTest.java?rev=1812621&r1=1812620&r2=1812621&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/JcrNodeResourceIteratorTest.java (original)
+++ sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/JcrNodeResourceIteratorTest.java Thu Oct 19 11:42:07 2017
@@ -26,6 +26,7 @@ import javax.jcr.NodeIterator;
 import javax.jcr.RepositoryException;
 
 import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.URIProvider;
 import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
 import org.apache.sling.commons.testing.jcr.MockNode;
 import org.apache.sling.commons.testing.jcr.MockNodeIterator;
@@ -37,7 +38,7 @@ import junit.framework.TestCase;
 public class JcrNodeResourceIteratorTest extends TestCase {
 
     private HelperData getHelperData() {
-        return new HelperData(new AtomicReference<DynamicClassLoaderManager>());
+        return new HelperData(new AtomicReference<DynamicClassLoaderManager>(), new AtomicReference<URIProvider[]>());
     }
 
     public void testEmpty() {

Modified: sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceFactoryTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceFactoryTest.java?rev=1812621&r1=1812620&r2=1812621&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceFactoryTest.java (original)
+++ sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceFactoryTest.java Thu Oct 19 11:42:07 2017
@@ -29,6 +29,7 @@ import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 
 import org.apache.jackrabbit.commons.JcrUtils;
+import org.apache.sling.api.resource.URIProvider;
 import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
 import org.apache.sling.commons.testing.jcr.RepositoryTestBase;
 import org.apache.sling.jcr.resource.internal.HelperData;
@@ -87,7 +88,7 @@ public class JcrItemResourceFactoryTest
     }
 
     private void compareGetItemOrNull(String path, String expectedPath) throws RepositoryException {
-        HelperData helper = new HelperData(new AtomicReference<DynamicClassLoaderManager>());
+        HelperData helper = new HelperData(new AtomicReference<DynamicClassLoaderManager>(), new AtomicReference<URIProvider[]>());
         Item item1 = new JcrItemResourceFactory(session, helper).getItemOrNull(path);
         Item item2 = new JcrItemResourceFactory(nonJackrabbitSession, helper).getItemOrNull(path);
         if (expectedPath == null) {

Modified: sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceTest.java?rev=1812621&r1=1812620&r2=1812621&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceTest.java (original)
+++ sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceTest.java Thu Oct 19 11:42:07 2017
@@ -32,6 +32,7 @@ import javax.jcr.Session;
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceMetadata;
+import org.apache.sling.api.resource.URIProvider;
 import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
 import org.apache.sling.jcr.resource.api.JcrResourceConstants;
 import org.apache.sling.jcr.resource.internal.HelperData;
@@ -39,7 +40,7 @@ import org.apache.sling.jcr.resource.int
 public class JcrNodeResourceTest extends JcrItemResourceTestBase {
 
     private HelperData getHelperData() throws Exception {
-        return new HelperData(new AtomicReference<DynamicClassLoaderManager>());
+        return new HelperData(new AtomicReference<DynamicClassLoaderManager>(), new AtomicReference<URIProvider[]>());
     }
 
     public void testLinkedFile() throws Exception {

Modified: sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrTestNodeResource.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrTestNodeResource.java?rev=1812621&r1=1812620&r2=1812621&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrTestNodeResource.java (original)
+++ sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrTestNodeResource.java Thu Oct 19 11:42:07 2017
@@ -24,6 +24,7 @@ import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 
 import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.URIProvider;
 import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
 import org.apache.sling.jcr.resource.internal.HelperData;
 
@@ -31,7 +32,7 @@ public class JcrTestNodeResource extends
 
     public JcrTestNodeResource(ResourceResolver resourceResolver, Node node,
             ClassLoader dynamicClassLoader) throws RepositoryException {
-        super(resourceResolver, node.getPath(), null, node, new HelperData(new AtomicReference<DynamicClassLoaderManager>()));
+        super(resourceResolver, node.getPath(), null, node, new HelperData(new AtomicReference<DynamicClassLoaderManager>(), new AtomicReference<URIProvider[]>()));
     }
 
 }

Modified: sling/trunk/bundles/servlets/get/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/get/pom.xml?rev=1812621&r1=1812620&r2=1812621&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/get/pom.xml (original)
+++ sling/trunk/bundles/servlets/get/pom.xml Thu Oct 19 11:42:07 2017
@@ -92,7 +92,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.api</artifactId>
-            <version>2.7.0</version>
+            <version>2.16.3-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>

Modified: sling/trunk/bundles/servlets/get/src/main/java/org/apache/sling/servlets/get/impl/helpers/StreamRendererServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/get/src/main/java/org/apache/sling/servlets/get/impl/helpers/StreamRendererServlet.java?rev=1812621&r1=1812620&r2=1812621&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/get/src/main/java/org/apache/sling/servlets/get/impl/helpers/StreamRendererServlet.java (original)
+++ sling/trunk/bundles/servlets/get/src/main/java/org/apache/sling/servlets/get/impl/helpers/StreamRendererServlet.java Thu Oct 19 11:42:07 2017
@@ -42,6 +42,7 @@ import org.apache.sling.api.SlingConstan
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.SlingHttpServletResponse;
 import org.apache.sling.api.request.RequestDispatcherOptions;
+import org.apache.sling.api.resource.ExternalizableInputStream;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceMetadata;
 import org.apache.sling.api.resource.ResourceNotFoundException;
@@ -50,6 +51,7 @@ import org.apache.sling.api.resource.Res
 import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.api.servlets.HttpConstants;
 import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
+import org.apache.sling.api.resource.ExternalizableInputStream;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -167,6 +169,10 @@ public class StreamRendererServlet exten
         }
         InputStream stream = resource.adaptTo(InputStream.class);
         if (stream != null) {
+            if ( stream instanceof ExternalizableInputStream) {
+                response.sendRedirect(((ExternalizableInputStream)stream).getURI().toString());
+                return;
+            }
             if (isHeadRequest(request)) {
                 setContentLength(response, resource.getResourceMetadata().getContentLength());
                 setHeaders(resource, response);

Modified: sling/trunk/launchpad/builder/src/main/provisioning/sling.txt
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/builder/src/main/provisioning/sling.txt?rev=1812621&r1=1812620&r2=1812621&view=diff
==============================================================================
--- sling/trunk/launchpad/builder/src/main/provisioning/sling.txt (original)
+++ sling/trunk/launchpad/builder/src/main/provisioning/sling.txt Thu Oct 19 11:42:07 2017
@@ -35,7 +35,7 @@
     org.apache.httpcomponents/httpcore-osgi/4.4.1
     org.apache.httpcomponents/httpclient-osgi/4.4.1
     org.apache.sling/org.apache.sling.adapter/2.1.10
-    org.apache.sling/org.apache.sling.api/2.16.2
+    org.apache.sling/org.apache.sling.api/2.16.3-SNAPSHOT
     org.apache.sling/org.apache.sling.auth.core/1.4.0
     org.apache.sling/org.apache.sling.auth.form/1.0.8
     org.apache.sling/org.apache.sling.bundleresource.impl/2.2.0
@@ -55,13 +55,13 @@
     org.apache.sling/org.apache.sling.installer.console/1.0.2
     org.apache.sling/org.apache.sling.installer.provider.jcr/3.1.26
     org.apache.sling/org.apache.sling.jcr.contentloader/2.2.4
-    org.apache.sling/org.apache.sling.jcr.resource/3.0.4
+    org.apache.sling/org.apache.sling.jcr.resource/3.0.5-SNAPSHOT
     org.apache.sling/org.apache.sling.launchpad.content/2.0.12
     org.apache.sling/org.apache.sling.models.api/1.3.4
     org.apache.sling/org.apache.sling.models.impl/1.4.2
-    org.apache.sling/org.apache.sling.resourceresolver/1.5.30
+    org.apache.sling/org.apache.sling.resourceresolver/1.5.31-SNAPSHOT
     org.apache.sling/org.apache.sling.serviceusermapper/1.3.4
-    org.apache.sling/org.apache.sling.servlets.get/2.1.26
+    org.apache.sling/org.apache.sling.servlets.get/2.1.27-SNAPSHOT
     org.apache.sling/org.apache.sling.servlets.post/2.3.22
     org.apache.sling/org.apache.sling.servlets.resolver/2.4.14
     org.apache.sling/org.apache.sling.xss/2.0.0