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

rombert pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-commons-fsclassloader.git

commit 63e103c6f30112a7a6c837ba57a31c9feff0d83b
Author: Radu Cotescu <[email protected]>
AuthorDate: Tue May 12 15:48:23 2015 +0000

    SLING-4708 -  Move the File System Classloader from contrib to bundles
    
    * moved fsclassloader to bundles and updated SCM info
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1678983 
13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            | 103 ++++++++
 .../fsclassloader/impl/FSClassLoaderProvider.java  | 270 +++++++++++++++++++++
 .../fsclassloader/impl/FSDynamicClassLoader.java   |  72 ++++++
 3 files changed, 445 insertions(+)

diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..6f6630a
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+    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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
+
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.sling</groupId>
+        <artifactId>sling</artifactId>
+        <version>22</version>
+    </parent>
+
+    <artifactId>org.apache.sling.commons.fsclassloader</artifactId>
+    <version>1.0.1-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+
+    <name>Apache Sling Commons FileSystem ClassLoader</name>
+    <description>
+        The Sling Commons FileSystem ClassLoader bundle provides a dynamic 
class loader for reading
+        and writing class files from and to the file system.
+    </description>
+
+    <scm>
+        
<connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/bundles/commons/fsclassloader</connection>
+        
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/bundles/commons/fsclassloader</developerConnection>
+        
<url>http://svn.apache.org/viewvc/sling/trunk/bundles/commons/fsclassloader</url>
+    </scm>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-scr-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Private-Package>
+                            org.apache.sling.commons.fsclassloader.impl
+                        </Private-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <reporting>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <configuration>
+                    <excludePackageNames>
+                        org.apache.sling.commons.fsclassloader.impl
+                    </excludePackageNames>
+                </configuration>
+            </plugin>
+        </plugins>
+    </reporting>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr.annotations</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.classloader</artifactId>
+            <version>1.3.0</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git 
a/src/main/java/org/apache/sling/commons/fsclassloader/impl/FSClassLoaderProvider.java
 
b/src/main/java/org/apache/sling/commons/fsclassloader/impl/FSClassLoaderProvider.java
new file mode 100644
index 0000000..74d2a2f
--- /dev/null
+++ 
b/src/main/java/org/apache/sling/commons/fsclassloader/impl/FSClassLoaderProvider.java
@@ -0,0 +1,270 @@
+/*
+ * 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.commons.fsclassloader.impl;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.commons.classloader.ClassLoaderWriter;
+import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The <code>FSClassLoaderProvider</code> is a dynamic class loader provider
+ * which uses the file system to store and read class files from.
+ *
+ */
+@Component
+@Service(value={ClassLoaderWriter.class}, serviceFactory = true)
+@Property( name=Constants.SERVICE_RANKING, intValue=100)
+public class FSClassLoaderProvider
+    implements ClassLoaderWriter {
+
+    /** File root */
+    private File root;
+
+    /** File root URL */
+    private URL rootURL;
+
+    /** Current class loader */
+    private FSDynamicClassLoader loader;
+
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    @Reference(
+            referenceInterface = DynamicClassLoaderManager.class,
+            bind = "bindDynamicClassLoaderManager",
+            unbind = "unbindDynamicClassLoaderManager")
+    private ServiceReference dynamicClassLoaderManager;
+
+    /** The bundle asking for this service instance */
+    private Bundle callerBundle;
+
+    /**
+     * Activate this component.
+     * Create the root directory.
+     * @param componentContext
+     * @throws MalformedURLException
+     */
+    @Activate
+    protected void activate(final ComponentContext componentContext) throws 
MalformedURLException {
+        // get the file root
+        this.root = new 
File(componentContext.getBundleContext().getDataFile(""), "classes");
+        this.root.mkdirs();
+        this.rootURL = this.root.toURI().toURL();
+        this.callerBundle = componentContext.getUsingBundle();
+    }
+
+    /**
+     * Deactivate this component.
+     * Create the root directory.
+     */
+    @Deactivate
+    protected void deactivate() {
+        this.root = null;
+        this.rootURL = null;
+        this.destroyClassLoader();
+    }
+
+    /**
+     * Called to handle binding the DynamicClassLoaderManager service
+     * reference
+     */
+    @SuppressWarnings("unused")
+    private void bindDynamicClassLoaderManager(final ServiceReference ref) {
+        this.dynamicClassLoaderManager = ref;
+    }
+
+    /**
+     * Called to handle unbinding of the DynamicClassLoaderManager service
+     * reference
+     */
+    @SuppressWarnings("unused")
+    private void unbindDynamicClassLoaderManager(final ServiceReference ref) {
+        if (this.dynamicClassLoaderManager == ref) {
+            this.dynamicClassLoaderManager = null;
+        }
+    }
+
+    private void destroyClassLoader() {
+        final ClassLoader rcl = this.loader;
+        if (rcl != null) {
+            this.loader = null;
+
+            final ServiceReference localDynamicClassLoaderManager = 
this.dynamicClassLoaderManager;
+            final Bundle localCallerBundle = this.callerBundle;
+            if ( localDynamicClassLoaderManager != null && localCallerBundle 
!= null ) {
+                
localCallerBundle.getBundleContext().ungetService(localDynamicClassLoaderManager);
+            }
+        }
+    }
+
+    /**
+     * @see 
org.apache.sling.commons.classloader.ClassLoaderWriter#getClassLoader()
+     */
+    public ClassLoader getClassLoader() {
+        synchronized ( this ) {
+            if ( loader == null || !loader.isLive() ) {
+                this.destroyClassLoader();
+                // get the dynamic class loader for the bundle using this
+                // class loader writer
+                final DynamicClassLoaderManager dclm = 
(DynamicClassLoaderManager) this.callerBundle.getBundleContext().getService(
+                    this.dynamicClassLoaderManager);
+
+                loader = new FSDynamicClassLoader(new URL[] {this.rootURL}, 
dclm.getDynamicClassLoader());
+            }
+            return this.loader;
+        }
+    }
+
+    private void checkClassLoader(final String filePath) {
+        synchronized ( this ) {
+            final FSDynamicClassLoader currentLoader = this.loader;
+            if ( currentLoader != null && filePath.endsWith(".class") ) {
+                // remove store directory and .class
+                final String path = 
filePath.substring(this.root.getAbsolutePath().length() + 1, filePath.length() 
- 6);
+                // convert to a class name
+                final String className = path.replace(File.separatorChar, '.');
+                currentLoader.check(className);
+            }
+        }
+    }
+
+    //---------- SCR Integration ----------------------------------------------
+
+    /**
+     * @see 
org.apache.sling.commons.classloader.ClassLoaderWriter#delete(java.lang.String)
+     */
+    public boolean delete(final String name) {
+        final String path = cleanPath(name);
+        final File file = new File(path);
+        if ( file.exists() ) {
+            final boolean result = file.delete();
+            logger.debug("Deleted {} : {}", name,result);
+            if ( result ) {
+                this.checkClassLoader(file.getAbsolutePath());
+            }
+
+            return result;
+        }
+        // file does not exist so we return false
+        return false;
+    }
+
+    /**
+     * @see 
org.apache.sling.commons.classloader.ClassLoaderWriter#getOutputStream(java.lang.String)
+     */
+    public OutputStream getOutputStream(final String name) {
+        logger.debug("Get stream for {}", name);
+        final String path = cleanPath(name);
+        final File file = new File(path);
+        final File parentDir = file.getParentFile();
+        if ( !parentDir.exists() ) {
+            parentDir.mkdirs();
+        }
+        try {
+            if ( file.exists() ) {
+                this.checkClassLoader(path);
+            }
+            return new FileOutputStream(path);
+        } catch (FileNotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * @see 
org.apache.sling.commons.classloader.ClassLoaderWriter#rename(java.lang.String, 
java.lang.String)
+     */
+    public boolean rename(final String oldName, final String newName) {
+        logger.debug("Rename {} to {}", oldName, newName);
+        final String oldPath = cleanPath(oldName);
+        final String newPath = cleanPath(newName);
+        final File old = new File(oldPath);
+        final boolean result = old.renameTo(new File(newPath));
+        if ( result ) {
+            this.checkClassLoader(oldPath);
+            this.checkClassLoader(newPath);
+        }
+        return result;
+    }
+
+    /**
+     * Clean the path by converting slashes to the correct format
+     * and prefixing the root directory.
+     * @param path The path
+     * @return The file path
+     */
+    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 ( File.separatorChar != '/') {
+            path = path.replace('/', File.separatorChar);
+        }
+        return this.root.getAbsolutePath() + path;
+    }
+
+    /**
+     * @see 
org.apache.sling.commons.classloader.ClassLoaderWriter#getInputStream(java.lang.String)
+     */
+    public InputStream getInputStream(final String name)
+    throws IOException {
+        logger.debug("Get input stream of {}", name);
+        final String path = cleanPath(name);
+        final File file = new File(path);
+        return new FileInputStream(file);
+    }
+
+    /**
+     * @see 
org.apache.sling.commons.classloader.ClassLoaderWriter#getLastModified(java.lang.String)
+     */
+    public long getLastModified(final String name) {
+        logger.debug("Get last modified of {}", name);
+        final String path = cleanPath(name);
+        final File file = new File(path);
+        if ( file.exists() ) {
+            return file.lastModified();
+        }
+
+        // fallback to "non-existant" in case of problems
+        return -1;
+    }
+}
diff --git 
a/src/main/java/org/apache/sling/commons/fsclassloader/impl/FSDynamicClassLoader.java
 
b/src/main/java/org/apache/sling/commons/fsclassloader/impl/FSDynamicClassLoader.java
new file mode 100644
index 0000000..d35ae3d
--- /dev/null
+++ 
b/src/main/java/org/apache/sling/commons/fsclassloader/impl/FSDynamicClassLoader.java
@@ -0,0 +1,72 @@
+/*
+ * 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.commons.fsclassloader.impl;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.sling.commons.classloader.DynamicClassLoader;
+
+public class FSDynamicClassLoader
+    extends URLClassLoader
+    implements DynamicClassLoader {
+
+    private boolean isDirty = false;
+
+    private final Set<String> hit = Collections.synchronizedSet(new 
HashSet<String>());
+    private final Set<String> miss = Collections.synchronizedSet(new 
HashSet<String>());
+
+    private final DynamicClassLoader parentLoader;
+
+    public FSDynamicClassLoader(final URL[] urls, final ClassLoader parent) {
+        super(urls, parent);
+        parentLoader = (parent instanceof DynamicClassLoader ? 
(DynamicClassLoader)parent : null);
+    }
+
+    /**
+     * @see org.apache.sling.commons.classloader.DynamicClassLoader#isLive()
+     */
+    public boolean isLive() {
+        return !isDirty && (parentLoader == null || parentLoader.isLive());
+    }
+
+    /**
+     * @see java.lang.ClassLoader#loadClass(java.lang.String)
+     */
+    @Override
+    public Class<?> loadClass(final String name) throws ClassNotFoundException 
{
+        try {
+            final Class<?> c = super.loadClass(name);
+            this.hit.add(name);
+            return c;
+        } catch (final ClassNotFoundException cnfe) {
+            this.miss.add(name);
+            throw cnfe;
+        }
+    }
+
+    public void check(final String className) {
+        if ( !this.isDirty ) {
+            this.isDirty = hit.contains(className) || miss.contains(className);
+        }
+    }
+}

-- 
To stop receiving notification emails like this one, please contact
"[email protected]" <[email protected]>.

Reply via email to