You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 09:46:41 UTC

[sling-org-apache-sling-jcr-classloader] 02/08: SLING-1150 : Session is not closed in getLastModified SLING-1146 : DynamicClassLoaderProvider and ClassLoaderWriter should not be a service factory and refactored session handling SLING-1151 : Don't export jackrabbit classes

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.jcr.classloader-3.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-classloader.git

commit 4c0188fd212b88b577d4ebd372a4e7961a18b939
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Mon Oct 12 08:53:33 2009 +0000

    SLING-1150 : Session is not closed in getLastModified
    SLING-1146 : DynamicClassLoaderProvider and ClassLoaderWriter should not be a service factory and refactored session handling
    SLING-1151 : Don't export jackrabbit classes
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/jcr/classloader@824266 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            |  24 +-
 ...pl.java => DynamicClassLoaderProviderImpl.java} | 165 ++++----
 .../internal/RepositoryClassLoaderFacade.java      |  73 +---
 .../RepositoryClassLoaderProviderImpl.java         | 425 ++-------------------
 .../OSGI-INF/metatype/metatype.properties          |   8 +-
 5 files changed, 138 insertions(+), 557 deletions(-)

diff --git a/pom.xml b/pom.xml
index d643d20..6a0958a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.apache.sling</groupId>
         <artifactId>sling</artifactId>
-        <version>6</version>
+        <version>7</version>
         <relativePath>../../../parent/pom.xml</relativePath>
     </parent>
 
@@ -59,14 +59,14 @@
                             sling,jcr,jackrabbit
                         </Bundle-Category>
                         <Export-Package>
-                            org.apache.sling.jcr.classloader;version=${pom.version},
-                            org.apache.jackrabbit.classloader;
-                            org.apache.jackrabbit.net;version=1.4
+                            org.apache.sling.jcr.classloader;version=${pom.version}
                         </Export-Package>
                         <Private-Package>
                             org.apache.sling.jcr.classloader.internal.*,
                             org.apache.jackrabbit;
+                            org.apache.jackrabbit.classloader;
                             org.apache.jackrabbit.name;
+                            org.apache.jackrabbit.net;
                             org.apache.jackrabbit.util;split-package:=merge-first
                         </Private-Package>
                     </instructions>
@@ -88,31 +88,38 @@
         </plugins>
     </reporting>
     <dependencies>
+       <dependency>
+           <groupId>javax.jcr</groupId>
+           <artifactId>jcr</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.jcr.api</artifactId>
             <version>2.0.2-incubator</version>
+            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.commons.classloader</artifactId>
             <version>0.9.0</version>
+            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.commons.mime</artifactId>
             <version>2.1.0-incubator</version>
+            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.jackrabbit</groupId>
             <artifactId>jackrabbit-classloader</artifactId>
-            <version>1.4.1</version>
+            <version>1.5.0</version>
             <scope>compile</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.jackrabbit</groupId>
             <artifactId>jackrabbit-jcr-commons</artifactId>
-            <version>1.4.2</version>
+            <version>1.6.0</version>
             <scope>compile</scope>
         </dependency>
         <dependency>
@@ -127,13 +134,14 @@
             <groupId>commons-collections</groupId>
             <artifactId>commons-collections</artifactId>
             <version>3.2.1</version>
+            <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>org.apache.felix</groupId>
+            <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.apache.felix</groupId>
+            <groupId>org.osgi</groupId>
             <artifactId>org.osgi.compendium</artifactId>
         </dependency>
     </dependencies>
diff --git a/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoaderProviderImpl.java b/src/main/java/org/apache/sling/jcr/classloader/internal/DynamicClassLoaderProviderImpl.java
similarity index 76%
copy from src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoaderProviderImpl.java
copy to src/main/java/org/apache/sling/jcr/classloader/internal/DynamicClassLoaderProviderImpl.java
index 8187c3a..8dd5f3c 100644
--- a/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoaderProviderImpl.java
+++ b/src/main/java/org/apache/sling/jcr/classloader/internal/DynamicClassLoaderProviderImpl.java
@@ -25,7 +25,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.Dictionary;
-import java.util.Iterator;
 
 import javax.jcr.Item;
 import javax.jcr.Node;
@@ -34,50 +33,52 @@ import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.SimpleCredentials;
 
-import org.apache.commons.collections.BidiMap;
-import org.apache.commons.collections.bidimap.DualHashBidiMap;
 import org.apache.sling.commons.classloader.ClassLoaderWriter;
 import org.apache.sling.commons.classloader.DynamicClassLoaderProvider;
 import org.apache.sling.commons.mime.MimeTypeService;
 import org.apache.sling.jcr.api.SlingRepository;
-import org.apache.sling.jcr.classloader.RepositoryClassLoaderProvider;
-import org.osgi.framework.Bundle;
 import org.osgi.service.component.ComponentContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * The <code>RepositoryClassLoaderProviderImpl</code> TODO
+ * The <code>DynamicClassLoaderProviderImpl</code> TODO
  *
- * @scr.component immediate="false" label="%loader.name"
+ * @scr.component label="%loader.name"
  *      description="%loader.description"
  * @scr.property name="service.vendor" value="The Apache Software Foundation"
  * @scr.property name="service.description"
  *      value="Provides Repository ClassLoaders"
- * @scr.service servicefactory="true"
+ * @scr.service interface="DynamicClassLoaderProvider"
+ * @scr.service interface="ClassLoaderWriter"
  */
-public class RepositoryClassLoaderProviderImpl
-        implements RepositoryClassLoaderProvider, DynamicClassLoaderProvider, ClassLoaderWriter {
+public class DynamicClassLoaderProviderImpl
+        implements DynamicClassLoaderProvider, ClassLoaderWriter {
 
     /** default log */
-    private static final Logger log = LoggerFactory.getLogger(RepositoryClassLoaderFacade.class);
+    private final Logger log = LoggerFactory.getLogger(RepositoryClassLoaderFacade.class);
 
     /**
-     * @scr.property values0="/var/classes"
+     * @scr.property valueRefs0="CLASS_PATH_DEFAULT"
      */
     public static final String CLASS_PATH_PROP = "classpath";
 
+    public static final String CLASS_PATH_DEFAULT = "/var/classes";
+
     /**
      * @scr.property valueRef="OWNER_DEFAULT"
      */
     public static final String OWNER_PROP = "owner";
 
-    // JSP Class Loader class path will be injected to the class loader !
-    private static final String[] CLASS_PATH_DEFAULT = { };
+    /** Default class loader owner. */
+    public static final String OWNER_DEFAULT = "admin";
+
+    /** The owner of the class loader / jcr user. */
+    private String classLoaderOwner;
 
-    private static final String OWNER_DEFAULT = "admin";
 
-    private BidiMap loaders = new DualHashBidiMap();
+    /** JSP Class Loader class path will be injected to the class loader. */
+    private static final String[] CLASS_PATH_EMPTY = { };
 
     /**
      * @scr.reference
@@ -86,44 +87,26 @@ public class RepositoryClassLoaderProviderImpl
 
     private String[] classPath;
 
-    private String classLoaderOwner;
-
-    private BundleProxyClassLoader parent;
+    private RepositoryClassLoaderFacade facade;
 
     /** @scr.reference policy="dynamic" */
     private MimeTypeService mimeTypeService;
 
-    public ClassLoader getClassLoader(String owner) {
-        String classLoaderOwner = this.getClassLoaderOwner(owner);
-        RepositoryClassLoaderFacade loader =
-            (RepositoryClassLoaderFacade) this.loaders.get(classLoaderOwner);
-        if (loader == null) {
-            loader = new RepositoryClassLoaderFacade(this, this.parent,
-                classLoaderOwner, this.classPath);
-            this.loaders.put(classLoaderOwner, loader);
-        }
-
-        return loader;
-    }
+    /** The read session. */
+    private Session readSession;
 
-    public void ungetClassLoader(ClassLoader classLoader) {
-        // nothing to do
-    }
-
-    //---------- Support for RepositoryClassLoaderFacade ----------------------
-
-    /* package */ Session getSession(String owner) throws RepositoryException {
+    Session getSession() throws RepositoryException {
         // get an administrative session for potentiall impersonation
-        Session admin = this.repository.loginAdministrative(null);
+        final Session admin = this.repository.loginAdministrative(null);
 
         // do use the admin session, if the admin's user id is the same as owner
-        if (admin.getUserID().equals(owner)) {
+        if (admin.getUserID().equals(this.getOwnerId())) {
             return admin;
         }
 
         // else impersonate as the owner and logout the admin session again
         try {
-            return admin.impersonate(new SimpleCredentials(owner, new char[0]));
+            return admin.impersonate(new SimpleCredentials(this.getOwnerId(), new char[0]));
         } finally {
             admin.logout();
         }
@@ -133,17 +116,11 @@ public class RepositoryClassLoaderProviderImpl
      * @see org.apache.sling.commons.classloader.DynamicClassLoaderProvider#getClassLoader(ClassLoader)
      */
     public ClassLoader getClassLoader(final ClassLoader parent) {
-        // we just make up a unique identifier
-        final String classLoaderOwner = "DynamicClassLoaderProvider:" + parent.hashCode();
-        RepositoryClassLoaderFacade loader =
-            (RepositoryClassLoaderFacade) this.loaders.get(classLoaderOwner);
-        if (loader == null) {
-            loader = new RepositoryClassLoaderFacade(this, parent,
-                    this.classLoaderOwner, this.classPath);
-            this.loaders.put(classLoaderOwner, loader);
+        if ( this.facade == null ) {
+            this.facade = new RepositoryClassLoaderFacade(this, parent, this.getClassPaths());
         }
 
-        return loader;
+        return this.facade;
     }
 
     //---------- SCR Integration ----------------------------------------------
@@ -156,7 +133,7 @@ public class RepositoryClassLoaderProviderImpl
         Node parentNode = null;
         Session session = null;
         try {
-            session = getSession(this.classLoaderOwner);
+            session = getSession();
             if (session.itemExists(name)) {
                 Item fileItem = session.getItem(name);
                 parentNode = fileItem.getParent();
@@ -194,7 +171,7 @@ public class RepositoryClassLoaderProviderImpl
             oldName = cleanPath(oldName);
             newName = cleanPath(newName);
 
-            session = this.getSession(this.classLoaderOwner);
+            session = this.getSession();
             session.getWorkspace().move(oldName, newName);
             return true;
         } catch (RepositoryException re) {
@@ -251,7 +228,7 @@ public class RepositoryClassLoaderProviderImpl
         return false;
     }
 
-    private static void checkNode(Node node, String path) {
+    private void checkNode(Node node, String path) {
         if (node != null && node.isModified()) {
             try {
                 node.refresh(false);
@@ -279,11 +256,11 @@ public class RepositoryClassLoaderProviderImpl
 
     private static class RepositoryOutputStream extends ByteArrayOutputStream {
 
-        private final RepositoryClassLoaderProviderImpl repositoryOutputProvider;
+        private final DynamicClassLoaderProviderImpl repositoryOutputProvider;
 
         private final String fileName;
 
-        RepositoryOutputStream(RepositoryClassLoaderProviderImpl repositoryOutputProvider,
+        RepositoryOutputStream(DynamicClassLoaderProviderImpl repositoryOutputProvider,
                 String fileName) {
             this.repositoryOutputProvider = repositoryOutputProvider;
             this.fileName = fileName;
@@ -295,7 +272,7 @@ public class RepositoryClassLoaderProviderImpl
             Node parentNode = null;
             Session session = null;
             try {
-                session = repositoryOutputProvider.getSession(repositoryOutputProvider.classLoaderOwner);
+                session = repositoryOutputProvider.getSession();
                 final int lastPos = fileName.lastIndexOf('/');
                 if ( lastPos != -1 ) {
                     repositoryOutputProvider.mkdirs(session, fileName.substring(0, lastPos));
@@ -366,11 +343,11 @@ public class RepositoryClassLoaderProviderImpl
 
                 parentNode.save();
             } catch (RepositoryException re) {
-                log.error("Cannot write file " + fileName, re);
+                repositoryOutputProvider.log.error("Cannot write file " + fileName, re);
                 throw new IOException("Cannot write file " + fileName
                     + ", reason: " + re.toString());
             } finally {
-                checkNode(parentNode, fileName);
+                repositoryOutputProvider.checkNode(parentNode, fileName);
                 if ( session != null ) {
                     session.logout();
                 }
@@ -386,7 +363,7 @@ public class RepositoryClassLoaderProviderImpl
         final String path = cleanPath(fileName) + "/jcr:content/jcr:data";
         Session session = null;
         try {
-            session = getSession(this.classLoaderOwner);
+            session = this.getReadSession();
             if ( session.itemExists(path) ) {
                 final Property prop = (Property)session.getItem(path);
                 return prop.getStream();
@@ -395,10 +372,6 @@ public class RepositoryClassLoaderProviderImpl
         } catch (RepositoryException re) {
             throw (IOException) new IOException(
                         "Failed to get InputStream for " + fileName).initCause(re);
-        } finally {
-            if ( session != null ) {
-                session.logout();
-            }
         }
     }
 
@@ -409,7 +382,7 @@ public class RepositoryClassLoaderProviderImpl
         final String path = cleanPath(fileName) + "/jcr:content/jcr:lastModified";
         Session session = null;
         try {
-            session = getSession(this.classLoaderOwner);
+            session = this.getReadSession();
             if ( session.itemExists(path) ) {
                 final Property prop = (Property)session.getItem(path);
                 return prop.getLong();
@@ -422,40 +395,64 @@ public class RepositoryClassLoaderProviderImpl
         return -1;
     }
 
-    protected void activate(ComponentContext componentContext) {
+    /**
+     * Activate this component.
+     * @param componentContext
+     */
+    protected void activate(final ComponentContext componentContext) {
         @SuppressWarnings("unchecked")
         Dictionary properties = componentContext.getProperties();
 
         Object prop = properties.get(CLASS_PATH_PROP);
-        this.classPath = (prop instanceof String[]) ? (String[]) prop : CLASS_PATH_DEFAULT;
+        this.classPath = (prop instanceof String[]) ? (String[]) prop : CLASS_PATH_EMPTY;
 
         prop = properties.get(OWNER_PROP);
         this.classLoaderOwner = (prop instanceof String)? (String) prop : OWNER_DEFAULT;
+    }
 
-        Bundle owner = componentContext.getUsingBundle();
-
-        // if there is no using bundle, we have an error !!
-        if (owner == null) {
-            throw new IllegalStateException("Using Bundle expected. Is this a servicefactory component ?");
+    /**
+     * Deactivate this component
+     * @param componentContext
+     */
+    protected void deactivate(final ComponentContext componentContext) {
+        if ( this.facade != null) {
+            this.facade.destroy();
+            this.facade = null;
+        }
+        if ( this.readSession != null ) {
+            this.readSession.logout();
+            this.readSession = null;
         }
-
-        this.parent = new BundleProxyClassLoader(owner, null);
     }
 
-    @SuppressWarnings("unchecked")
-    protected void deactivate(ComponentContext componentContext) {
-        for (Iterator ci=this.loaders.values().iterator(); ci.hasNext(); ) {
-            RepositoryClassLoaderFacade cl = (RepositoryClassLoaderFacade) ci.next();
-            cl.destroy();
-            ci.remove();
-        }
+    /**
+     * Return the owner id
+     */
+    protected String getOwnerId() {
+        return this.classLoaderOwner;
+    }
 
-        this.parent = null;
+    /**
+     * Return the configured class paths
+     */
+    protected String[] getClassPaths() {
+        return this.classPath;
     }
 
-    //---------- internal -----------------------------------------------------
+    public synchronized Session getReadSession() throws RepositoryException {
+        // check current session
+        if (this.readSession != null) {
+            if (this.readSession.isLive()) {
+                return this.readSession;
+            }
 
-    private String getClassLoaderOwner(String userId) {
-        return this.classLoaderOwner;
+            // current session is not live anymore, drop
+            this.readSession.logout();
+            this.readSession = null;
+        }
+
+        // no session currently, acquire and return
+        this.readSession = this.getSession();
+        return this.readSession;
     }
 }
diff --git a/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoaderFacade.java b/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoaderFacade.java
index 9324105..f33a834 100644
--- a/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoaderFacade.java
+++ b/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoaderFacade.java
@@ -24,7 +24,6 @@ import java.net.URLClassLoader;
 import java.util.Enumeration;
 
 import javax.jcr.RepositoryException;
-import javax.jcr.Session;
 
 import org.apache.jackrabbit.classloader.DynamicRepositoryClassLoader;
 import org.slf4j.Logger;
@@ -36,21 +35,18 @@ import org.slf4j.LoggerFactory;
 class RepositoryClassLoaderFacade extends URLClassLoader {
 
     /** default log */
-    private static final Logger log = LoggerFactory.getLogger(RepositoryClassLoaderFacade.class);
+    private final Logger log = LoggerFactory.getLogger(RepositoryClassLoaderFacade.class);
 
     private static final URL[] NO_URLS = new URL[0];
 
-    private RepositoryClassLoaderProviderImpl classLoaderProvider;
+    private DynamicClassLoaderProviderImpl classLoaderProvider;
     private ClassLoader parent;
-    private String sessionOwner;
-    private Session session;
     private String[] classPath;
     private DynamicRepositoryClassLoader delegate;
 
     public RepositoryClassLoaderFacade(
-            RepositoryClassLoaderProviderImpl classLoaderProvider,
+            DynamicClassLoaderProviderImpl classLoaderProvider,
             ClassLoader parent,
-            String sessionOwner,
             String[] classPath) {
 
         // no parent class loader, we delegate to repository class loaders
@@ -59,26 +55,6 @@ class RepositoryClassLoaderFacade extends URLClassLoader {
         this.classLoaderProvider = classLoaderProvider;
         this.parent = parent;
         this.classPath = classPath;
-        this.sessionOwner = sessionOwner;
-    }
-
-    public void addPath(String path) {
-        // create new class path
-        String[] newClassPath = new String[this.classPath.length+1];
-        System.arraycopy(this.classPath, 0, newClassPath, 0, this.classPath.length);
-        newClassPath[this.classPath.length] = path;
-        this.classPath = newClassPath;
-
-        // destroy the delegate and have a new one created
-        if (this.delegate != null) {
-            DynamicRepositoryClassLoader oldLoader = this.delegate;
-            this.delegate = null;
-            oldLoader.destroy();
-        }
-    }
-
-    public String[] getClassPath() {
-        return this.classPath.clone();
     }
 
     @Override
@@ -117,54 +93,25 @@ class RepositoryClassLoaderFacade extends URLClassLoader {
         }
     }
 
-    //---------- Reference counting support -----------------------------------
-
-    /* package */ void destroy() {
+    void destroy() {
         if (this.delegate != null) {
             this.delegate.destroy();
             this.delegate = null;
         }
-
-        if (this.session != null) {
-            this.session.logout();
-            this.session = null;
-        }
     }
 
     //---------- internal -----------------------------------------------------
 
-    private Session getSession() throws RepositoryException {
-        // check current session
-        if (this.session != null) {
-            if (this.session.isLive()) {
-                return this.session;
-            }
+    private synchronized DynamicRepositoryClassLoader getDelegateClassLoader() throws RepositoryException {
+        if ( this.delegate == null ) {
+            this.delegate = new DynamicRepositoryClassLoader( this.classLoaderProvider.getReadSession(), this.classPath, this.parent);
 
-            // drop delegate
-            if (this.delegate != null) {
-                this.delegate.destroy();
-                this.delegate = null;
-            }
-
-            // current session is not live anymore, drop
-            this.session.logout();
-            this.session = null;
-        }
-
-        // no session currently, acquire and return
-        this.session = this.classLoaderProvider.getSession(this.sessionOwner);
-        return this.session;
-    }
-
-    private DynamicRepositoryClassLoader getDelegateClassLoader() throws RepositoryException {
-        if (this.delegate != null) {
+        } else {
             if (this.delegate.isDirty()) {
-                this.delegate = this.delegate.reinstantiate(this.getSession(), this.parent);
+                this.delegate = this.delegate.reinstantiate(this.classLoaderProvider.getReadSession(), this.parent);
             }
-        } else {
-            this.delegate = new DynamicRepositoryClassLoader(this.getSession(), this.classPath, this.parent);
-        }
 
+        }
         return this.delegate;
     }
 
diff --git a/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoaderProviderImpl.java b/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoaderProviderImpl.java
index 8187c3a..389a585 100644
--- a/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoaderProviderImpl.java
+++ b/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoaderProviderImpl.java
@@ -18,444 +18,69 @@
  */
 package org.apache.sling.jcr.classloader.internal;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Dictionary;
-import java.util.Iterator;
-
-import javax.jcr.Item;
-import javax.jcr.Node;
-import javax.jcr.Property;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.SimpleCredentials;
-
-import org.apache.commons.collections.BidiMap;
-import org.apache.commons.collections.bidimap.DualHashBidiMap;
-import org.apache.sling.commons.classloader.ClassLoaderWriter;
-import org.apache.sling.commons.classloader.DynamicClassLoaderProvider;
-import org.apache.sling.commons.mime.MimeTypeService;
-import org.apache.sling.jcr.api.SlingRepository;
 import org.apache.sling.jcr.classloader.RepositoryClassLoaderProvider;
 import org.osgi.framework.Bundle;
 import org.osgi.service.component.ComponentContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * The <code>RepositoryClassLoaderProviderImpl</code> TODO
  *
- * @scr.component immediate="false" label="%loader.name"
- *      description="%loader.description"
+ * @scr.component inherit="false" label="%deprecatedloader.name"
+ *      description="%deprecatedloader.description"
  * @scr.property name="service.vendor" value="The Apache Software Foundation"
  * @scr.property name="service.description"
  *      value="Provides Repository ClassLoaders"
- * @scr.service servicefactory="true"
+ * @scr.service servicefactory="true" interface="RepositoryClassLoaderProvider"
+ * @scr.property nameRef="DynamicClassLoaderProviderImpl.CLASS_PATH_PROP" valueRefs0="DynamicClassLoaderProviderImpl.CLASS_PATH_DEFAULT"
+ * @scr.property nameRef="DynamicClassLoaderProviderImpl.OWNER_PROP" valueRef="DynamicClassLoaderProviderImpl.OWNER_DEFAULT"
+ * @scr.reference name="repository" interface="org.apache.sling.jcr.api.SlingRepository"
+ * @scr.reference name="mimeTypeService" policy="dynamic" interface="org.apache.sling.commons.mime.MimeTypeService"
  */
 public class RepositoryClassLoaderProviderImpl
-        implements RepositoryClassLoaderProvider, DynamicClassLoaderProvider, ClassLoaderWriter {
-
-    /** default log */
-    private static final Logger log = LoggerFactory.getLogger(RepositoryClassLoaderFacade.class);
-
-    /**
-     * @scr.property values0="/var/classes"
-     */
-    public static final String CLASS_PATH_PROP = "classpath";
-
-    /**
-     * @scr.property valueRef="OWNER_DEFAULT"
-     */
-    public static final String OWNER_PROP = "owner";
-
-    // JSP Class Loader class path will be injected to the class loader !
-    private static final String[] CLASS_PATH_DEFAULT = { };
-
-    private static final String OWNER_DEFAULT = "admin";
-
-    private BidiMap loaders = new DualHashBidiMap();
-
-    /**
-     * @scr.reference
-     */
-    private SlingRepository repository;
-
-    private String[] classPath;
-
-    private String classLoaderOwner;
+        extends DynamicClassLoaderProviderImpl
+        implements RepositoryClassLoaderProvider {
 
     private BundleProxyClassLoader parent;
 
-    /** @scr.reference policy="dynamic" */
-    private MimeTypeService mimeTypeService;
-
-    public ClassLoader getClassLoader(String owner) {
-        String classLoaderOwner = this.getClassLoaderOwner(owner);
-        RepositoryClassLoaderFacade loader =
-            (RepositoryClassLoaderFacade) this.loaders.get(classLoaderOwner);
-        if (loader == null) {
-            loader = new RepositoryClassLoaderFacade(this, this.parent,
-                classLoaderOwner, this.classPath);
-            this.loaders.put(classLoaderOwner, loader);
-        }
-
-        return loader;
-    }
-
-    public void ungetClassLoader(ClassLoader classLoader) {
-        // nothing to do
-    }
-
-    //---------- Support for RepositoryClassLoaderFacade ----------------------
-
-    /* package */ Session getSession(String owner) throws RepositoryException {
-        // get an administrative session for potentiall impersonation
-        Session admin = this.repository.loginAdministrative(null);
-
-        // do use the admin session, if the admin's user id is the same as owner
-        if (admin.getUserID().equals(owner)) {
-            return admin;
-        }
-
-        // else impersonate as the owner and logout the admin session again
-        try {
-            return admin.impersonate(new SimpleCredentials(owner, new char[0]));
-        } finally {
-            admin.logout();
-        }
-    }
+    private RepositoryClassLoaderFacade classLoaderFacade;
 
     /**
-     * @see org.apache.sling.commons.classloader.DynamicClassLoaderProvider#getClassLoader(ClassLoader)
+     * @see org.apache.sling.jcr.classloader.RepositoryClassLoaderProvider#getClassLoader(java.lang.String)
      */
-    public ClassLoader getClassLoader(final ClassLoader parent) {
-        // we just make up a unique identifier
-        final String classLoaderOwner = "DynamicClassLoaderProvider:" + parent.hashCode();
-        RepositoryClassLoaderFacade loader =
-            (RepositoryClassLoaderFacade) this.loaders.get(classLoaderOwner);
-        if (loader == null) {
-            loader = new RepositoryClassLoaderFacade(this, parent,
-                    this.classLoaderOwner, this.classPath);
-            this.loaders.put(classLoaderOwner, loader);
-        }
-
-        return loader;
-    }
-
-    //---------- SCR Integration ----------------------------------------------
-
-    /**
-     * @see org.apache.sling.commons.classloader.ClassLoaderWriter#delete(java.lang.String)
-     */
-    public boolean delete(String name) {
-        name = cleanPath(name);
-        Node parentNode = null;
-        Session session = null;
-        try {
-            session = getSession(this.classLoaderOwner);
-            if (session.itemExists(name)) {
-                Item fileItem = session.getItem(name);
-                parentNode = fileItem.getParent();
-                fileItem.remove();
-                parentNode.save();
-                return true;
-            }
-        } catch (RepositoryException re) {
-            log.error("Cannot remove " + name, re);
-        } finally {
-            checkNode(parentNode, name);
-            if ( session != null ) {
-                session.logout();
-            }
-        }
-
-        // fall back to false if item does not exist or in case of error
-        return false;
-    }
-
-    /**
-     * @see org.apache.sling.commons.classloader.ClassLoaderWriter#getOutputStream(java.lang.String)
-     */
-    public OutputStream getOutputStream(String name) {
-        final String path = cleanPath(name);
-        return new RepositoryOutputStream(this, path);
-    }
-
-    /**
-     * @see org.apache.sling.commons.classloader.ClassLoaderWriter#rename(java.lang.String, java.lang.String)
-     */
-    public boolean rename(String oldName, String newName) {
-        Session session = null;
-        try {
-            oldName = cleanPath(oldName);
-            newName = cleanPath(newName);
-
-            session = this.getSession(this.classLoaderOwner);
-            session.getWorkspace().move(oldName, newName);
-            return true;
-        } catch (RepositoryException re) {
-            log.error("Cannot rename " + oldName + " to " + newName, re);
-        } finally {
-            if ( session != null ) {
-                session.logout();
-            }
-        }
-
-        // fallback to false in case of error or non-existence of oldFileName
-        return false;
-    }
-
-    /**
-     * Creates a folder hierarchy in the repository.
-     */
-    private boolean mkdirs(final Session session, String path) {
-        Node parentNode = null;
-        try {
-            // quick test
-            if (session.itemExists(path) && session.getItem(path).isNode()) {
-                return true;
-            }
-
-            // check path walking it down
-            Node current = session.getRootNode();
-            String[] names = path.split("/");
-            for (int i = 0; i < names.length; i++) {
-                if (names[i] == null || names[i].length() == 0) {
-                    continue;
-                } else if (current.hasNode(names[i])) {
-                    current = current.getNode(names[i]);
-                } else {
-                    if (parentNode == null) {
-                        parentNode = current;
-                    }
-                    current = current.addNode(names[i], "nt:folder");
-                }
-            }
-
-            if (parentNode != null) {
-                parentNode.save();
-                return true;
-            }
-
-        } catch (RepositoryException re) {
-            log.error("Cannot create folder path " + path, re);
-        } finally {
-            checkNode(parentNode, path);
-        }
-
-        // false in case of error or no need to create
-        return false;
-    }
-
-    private static void checkNode(Node node, String path) {
-        if (node != null && node.isModified()) {
-            try {
-                node.refresh(false);
-            } catch (RepositoryException re) {
-                log.error("Cannot refresh node for " + path
-                    + " after failed save", re);
-            }
-        }
-    }
-
-    private String cleanPath(String path) {
-        // replace backslash by slash
-        path = path.replace('\\', '/');
-
-        // cut off trailing slash
-        while (path.endsWith("/")) {
-            path = path.substring(0, path.length() - 1);
-        }
-
-        if ( this.classPath == null || this.classPath.length == 0 ) {
-            return path;
-        }
-        return this.classPath[0] + path;
-    }
-
-    private static class RepositoryOutputStream extends ByteArrayOutputStream {
-
-        private final RepositoryClassLoaderProviderImpl repositoryOutputProvider;
-
-        private final String fileName;
-
-        RepositoryOutputStream(RepositoryClassLoaderProviderImpl repositoryOutputProvider,
-                String fileName) {
-            this.repositoryOutputProvider = repositoryOutputProvider;
-            this.fileName = fileName;
-        }
-
-        public void close() throws IOException {
-            super.close();
-
-            Node parentNode = null;
-            Session session = null;
-            try {
-                session = repositoryOutputProvider.getSession(repositoryOutputProvider.classLoaderOwner);
-                final int lastPos = fileName.lastIndexOf('/');
-                if ( lastPos != -1 ) {
-                    repositoryOutputProvider.mkdirs(session, fileName.substring(0, lastPos));
-                }
-                Node fileNode = null;
-                Node contentNode = null;
-                if (session.itemExists(fileName)) {
-                    Item item = session.getItem(fileName);
-                    if (item.isNode()) {
-                        Node node = item.isNode()
-                                ? (Node) item
-                                : item.getParent();
-                        if ("jcr:content".equals(node.getName())) {
-                            // replace the content properties of the jcr:content
-                            // node
-                            parentNode = node;
-                            contentNode = node;
-                        } else if (node.isNodeType("nt:file")) {
-                            // try to set the content properties of jcr:content
-                            // node
-                            parentNode = node;
-                            contentNode = node.getNode("jcr:content");
-                        } else { // fileName is a node
-                            // try to set the content properties of the node
-                            parentNode = node;
-                            contentNode = node;
-                        }
-                    } else {
-                        // replace property with an nt:file node (if possible)
-                        parentNode = item.getParent();
-                        String name = item.getName();
-                        fileNode = parentNode.addNode(name, "nt:file");
-                        item.remove();
-                    }
-                } else {
-                    int lastSlash = fileName.lastIndexOf('/');
-                    if (lastSlash <= 0) {
-                        parentNode = session.getRootNode();
-                    } else {
-                        Item parent = session.getItem(fileName.substring(0,
-                            lastSlash));
-                        if (!parent.isNode()) {
-                            // TODO: fail
-                        }
-                        parentNode = (Node) parent;
-                    }
-                    String name = fileName.substring(lastSlash + 1);
-                    fileNode = parentNode.addNode(name, "nt:file");
-                }
-
-                // if we have a file node, create the contentNode
-                if (fileNode != null) {
-                    contentNode = fileNode.addNode("jcr:content", "nt:resource");
-                }
-
-                final MimeTypeService mtService = this.repositoryOutputProvider.mimeTypeService;
-
-                String mimeType = (mtService == null ? null : mtService.getMimeType(fileName));
-                if (mimeType == null) {
-                    mimeType = "application/octet-stream";
-                }
-
-                contentNode.setProperty("jcr:lastModified",
-                    System.currentTimeMillis());
-                contentNode.setProperty("jcr:data", new ByteArrayInputStream(
-                    buf, 0, size()));
-                contentNode.setProperty("jcr:mimeType", mimeType);
-
-                parentNode.save();
-            } catch (RepositoryException re) {
-                log.error("Cannot write file " + fileName, re);
-                throw new IOException("Cannot write file " + fileName
-                    + ", reason: " + re.toString());
-            } finally {
-                checkNode(parentNode, fileName);
-                if ( session != null ) {
-                    session.logout();
-                }
-            }
+    public ClassLoader getClassLoader(String owner) {
+        if (this.classLoaderFacade == null) {
+            this.classLoaderFacade = new RepositoryClassLoaderFacade(this, this.parent,
+                this.getClassPaths());
         }
-    }
 
-    /**
-     * @see org.apache.sling.commons.classloader.ClassLoaderWriter#getInputStream(java.lang.String)
-     */
-    public InputStream getInputStream(String fileName)
-    throws IOException {
-        final String path = cleanPath(fileName) + "/jcr:content/jcr:data";
-        Session session = null;
-        try {
-            session = getSession(this.classLoaderOwner);
-            if ( session.itemExists(path) ) {
-                final Property prop = (Property)session.getItem(path);
-                return prop.getStream();
-            }
-            throw new FileNotFoundException("Unable to find " + fileName);
-        } catch (RepositoryException re) {
-            throw (IOException) new IOException(
-                        "Failed to get InputStream for " + fileName).initCause(re);
-        } finally {
-            if ( session != null ) {
-                session.logout();
-            }
-        }
+        return this.classLoaderFacade;
     }
 
     /**
-     * @see org.apache.sling.commons.classloader.ClassLoaderWriter#getLastModified(java.lang.String)
+     * @see org.apache.sling.jcr.classloader.RepositoryClassLoaderProvider#ungetClassLoader(java.lang.ClassLoader)
      */
-    public long getLastModified(String fileName) {
-        final String path = cleanPath(fileName) + "/jcr:content/jcr:lastModified";
-        Session session = null;
-        try {
-            session = getSession(this.classLoaderOwner);
-            if ( session.itemExists(path) ) {
-                final Property prop = (Property)session.getItem(path);
-                return prop.getLong();
-            }
-        } catch (RepositoryException se) {
-            log.error("Cannot get last modification time for " + fileName, se);
-        }
-
-        // fallback to "non-existant" in case of problems
-        return -1;
+    public void ungetClassLoader(ClassLoader classLoader) {
+        // nothing to do
     }
 
     protected void activate(ComponentContext componentContext) {
-        @SuppressWarnings("unchecked")
-        Dictionary properties = componentContext.getProperties();
-
-        Object prop = properties.get(CLASS_PATH_PROP);
-        this.classPath = (prop instanceof String[]) ? (String[]) prop : CLASS_PATH_DEFAULT;
-
-        prop = properties.get(OWNER_PROP);
-        this.classLoaderOwner = (prop instanceof String)? (String) prop : OWNER_DEFAULT;
-
-        Bundle owner = componentContext.getUsingBundle();
+        super.activate(componentContext);
+        final Bundle owner = componentContext.getUsingBundle();
 
         // if there is no using bundle, we have an error !!
         if (owner == null) {
             throw new IllegalStateException("Using Bundle expected. Is this a servicefactory component ?");
         }
-
         this.parent = new BundleProxyClassLoader(owner, null);
     }
 
     @SuppressWarnings("unchecked")
     protected void deactivate(ComponentContext componentContext) {
-        for (Iterator ci=this.loaders.values().iterator(); ci.hasNext(); ) {
-            RepositoryClassLoaderFacade cl = (RepositoryClassLoaderFacade) ci.next();
-            cl.destroy();
-            ci.remove();
+        if ( this.classLoaderFacade != null ) {
+            this.classLoaderFacade.destroy();
+            this.classLoaderFacade = null;
         }
-
         this.parent = null;
-    }
-
-    //---------- internal -----------------------------------------------------
-
-    private String getClassLoaderOwner(String userId) {
-        return this.classLoaderOwner;
+        super.deactivate(componentContext);
     }
 }
diff --git a/src/main/resources/OSGI-INF/metatype/metatype.properties b/src/main/resources/OSGI-INF/metatype/metatype.properties
index af0a38d..49b1383 100644
--- a/src/main/resources/OSGI-INF/metatype/metatype.properties
+++ b/src/main/resources/OSGI-INF/metatype/metatype.properties
@@ -22,13 +22,17 @@
 # descriptions as used in the metatype.xml descriptor generated by the
 # the Sling SCR plugin
 
-loader.name = Apache Sling Repository Class Loader Factory
-loader.description = Configuration for the Repository Class Loader Factory. This \
+deprecatedloader.name = Apache Sling Repository Class Loader Factory
+deprecatedloader.description = Configuration for the Repository Class Loader Factory. This \
  configuration applies to all clients of the factory even though each Bundle \
  using the factory retrieves its own factory. The class path of the created \
  Repository Class Loaders is configurable and the class loaders delegate use \
  the bundle asking for the factory as the parent class loader.
 
+loader.name = Apache Sling Repository Class Loader Factory
+loader.description = Configuration for the Repository Class Loader. The class path of the created \
+ Repository Class Loaders is configurable.
+
 classpath.name = Class Path
 classpath.description = The class path in the repository to use as the class \
  path for all created Repository Class Loaders. All Class Loaders are configured \

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.