SLING-2956 :  Store compiled classes in a cluster aware way 

git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1501227 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
index 0be5acf..5223936 100644
--- a/pom.xml
+++ b/pom.xml
@@ -103,6 +103,18 @@
         </dependency>
         <dependency>
             <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.osgi</artifactId>
+            <version>2.1.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.settings</artifactId>
+            <version>1.0.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.commons.mime</artifactId>
             <version>2.1.4</version>
             <scope>provided</scope>
diff --git a/src/main/java/org/apache/sling/jcr/classloader/internal/ClassLoaderWriterImpl.java b/src/main/java/org/apache/sling/jcr/classloader/internal/ClassLoaderWriterImpl.java
index fc44ced..2112ff2 100644
--- a/src/main/java/org/apache/sling/jcr/classloader/internal/ClassLoaderWriterImpl.java
+++ b/src/main/java/org/apache/sling/jcr/classloader/internal/ClassLoaderWriterImpl.java
@@ -44,7 +44,9 @@
 import org.apache.sling.commons.classloader.ClassLoaderWriter;
 import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
 import org.apache.sling.commons.mime.MimeTypeService;
+import org.apache.sling.commons.osgi.PropertiesUtil;
 import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.settings.SlingSettingsService;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.component.ComponentContext;
@@ -77,6 +79,11 @@
     @org.apache.felix.scr.annotations.Property(value=CLASS_PATH_DEFAULT)
     private static final String CLASS_PATH_PROP = "classpath";
 
+    private static final boolean APPEND_ID_DEFAULT = true;
+
+    @org.apache.felix.scr.annotations.Property(boolValue=APPEND_ID_DEFAULT)
+    private static final String APPEND_ID_PROP = "appendId";
+
     /** Node type for packages/folders. */
     private static final String NT_FOLDER = "nt:folder";
 
@@ -86,6 +93,8 @@
     @org.apache.felix.scr.annotations.Property(value=OWNER_DEFAULT)
     private static final String OWNER_PROP = "owner";
 
+    @Reference
+    private SlingSettingsService settings;
 
     /** The owner of the class loader / JCR user. */
     private String classLoaderOwner;
@@ -118,18 +127,15 @@
      */
     @Activate
     protected void activate(final ComponentContext componentContext, final Map<String, Object> properties) {
-        Object prop = properties.get(CLASS_PATH_PROP);
-        if ( prop instanceof String[] && ((String[])prop).length > 0 ) {
-            this.classPath = ((String[])prop)[0];
-        } else {
-            this.classPath = CLASS_PATH_DEFAULT;
-        }
+        this.classPath = PropertiesUtil.toString(properties.get(CLASS_PATH_PROP), CLASS_PATH_DEFAULT);
         if ( this.classPath.endsWith("/") ) {
             this.classPath = this.classPath.substring(0, this.classPath.length() - 1);
         }
+        if ( PropertiesUtil.toBoolean(properties.get(APPEND_ID_PROP), APPEND_ID_DEFAULT) ) {
+            this.classPath = this.classPath + '/' + this.settings.getSlingId();
+        }
 
-        prop = properties.get(OWNER_PROP);
-        this.classLoaderOwner = (prop instanceof String)? (String) prop : OWNER_DEFAULT;
+        this.classLoaderOwner = PropertiesUtil.toString(properties.get(OWNER_PROP), OWNER_DEFAULT);
 
         this.callerBundle = componentContext.getUsingBundle();
     }
@@ -330,7 +336,7 @@
                         // create the node "at the same time"
                         current = parentNode.addNode(names[i], NT_FOLDER);
                         session.save();
-                    } catch (RepositoryException re) {
+                    } catch (final RepositoryException re) {
                         // let's first refresh the session
                         // we don't catch an exception here, because if
                         // session refresh fails, we might have a serious problem!
diff --git a/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoader.java b/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoader.java
index 25ee7fe..6912bad 100644
--- a/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoader.java
+++ b/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoader.java
@@ -86,7 +86,7 @@
      * repository path.
      *
      * @param classPath The path making up the class path of this class
-     *                  loder
+     *                  loader
      * @param writer The class loader write to get a jcr session.
      * @param parent The parent <code>ClassLoader</code>, which may be
      *      <code>null</code>.
@@ -148,6 +148,7 @@
      * @throws ClassNotFoundException If the named class could not be found or
      *      if this class loader has already been destroyed.
      */
+    @Override
     protected Class<?> findClass(final String name) throws ClassNotFoundException {
         if (!this.writer.isActivate()) {
             throw new ClassNotFoundException(name + " (Classloader destroyed)");
@@ -177,6 +178,7 @@
      *      if the resource could not be found or if the class loader has
      *      already been destroyed.
      */
+    @Override
     public URL findResource(final String name) {
         if (!this.writer.isActivate()) {
             logger.warn("Destroyed class loader cannot find a resource: " + name, new IllegalStateException());
@@ -208,6 +210,7 @@
      *      empty enumeration if no resources are found by this class loader
      *      or if this class loader has already been destroyed.
      */
+    @Override
     public Enumeration<URL> findResources(final String name) {
         if (!this.writer.isActivate()) {
             logger.warn("Destroyed class loader cannot find a resources: " + name, new IllegalStateException());
@@ -395,6 +398,7 @@
     /**
      * Returns a string representation of this class loader.
      */
+    @Override
     public String toString() {
         StringBuilder buf = new StringBuilder(getClass().getName());
         if (destroyed) {
diff --git a/src/main/resources/OSGI-INF/metatype/metatype.properties b/src/main/resources/OSGI-INF/metatype/metatype.properties
index 247648b..566c60b 100644
--- a/src/main/resources/OSGI-INF/metatype/metatype.properties
+++ b/src/main/resources/OSGI-INF/metatype/metatype.properties
@@ -32,10 +32,13 @@
  with the same class path. This class path must include any destinations used \
  by Java compilers writing to the Repository such as the JSP Script Handler, \
  which by default writes to "/var/classes". If no class path is defined, the \
- "/var/classes" folder is used by default.
+ "/var/classes" folder is used by default. See also "Append Sling ID below".
 
 owner.name = Repository Session User
 owner.description = Name of a user owning the Repository Class Loader sessions. \
  If this is empty a simple administrative session is used. Otherwise the \
  administrative session is used to impersonate as the given user.
  
+appendId.name = Append Sling ID
+appendId.description = If this flag is enabled, the Sling ID is appended to the path \
+ to store/read class files from.
\ No newline at end of file