JAMES-2368 Rely on ExtendedClassLoader for MailboxListener loading

Refining loading strategy with SPI will be done all at once.


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/b6fbd098
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/b6fbd098
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/b6fbd098

Branch: refs/heads/master
Commit: b6fbd098167fc83aa53396720b3fce42c450e0a4
Parents: 9eceee1
Author: benwa <btell...@linagora.com>
Authored: Wed May 2 11:41:53 2018 +0700
Committer: benwa <btell...@linagora.com>
Committed: Fri May 4 13:38:02 2018 +0700

----------------------------------------------------------------------
 pom.xml                                         |  5 ++
 server/container/guice/guice-utils/pom.xml      | 52 +++++++++++++
 .../apache/james/utils/ExtendedClassLoader.java | 79 ++++++++++++++++++++
 server/container/guice/mailbox/pom.xml          |  4 +
 .../modules/mailbox/GlobalMailboxListeners.java | 25 +++----
 .../mailbox/GlobalMailboxListenersTest.java     | 15 +++-
 server/container/guice/mailet/pom.xml           |  4 +
 .../apache/james/utils/ExtendedClassLoader.java | 79 --------------------
 server/container/guice/pom.xml                  |  1 +
 9 files changed, 170 insertions(+), 94 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/b6fbd098/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index bc2ceb0..b7394be 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1161,6 +1161,11 @@
             </dependency>
             <dependency>
                 <groupId>${project.groupId}</groupId>
+                <artifactId>james-server-guice-utils</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>${project.groupId}</groupId>
                 <artifactId>james-server-guice-jmap</artifactId>
                 <version>${project.version}</version>
             </dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/b6fbd098/server/container/guice/guice-utils/pom.xml
----------------------------------------------------------------------
diff --git a/server/container/guice/guice-utils/pom.xml 
b/server/container/guice/guice-utils/pom.xml
new file mode 100644
index 0000000..12fea17
--- /dev/null
+++ b/server/container/guice/guice-utils/pom.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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/xsd/maven-4.0.0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.james</groupId>
+        <artifactId>james-server-guice</artifactId>
+        <version>3.1.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>james-server-guice-utils</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>james-server-filesystem-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>james-server-util-java8</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.github.fge</groupId>
+            <artifactId>throwing-lambdas</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/b6fbd098/server/container/guice/guice-utils/src/main/java/org/apache/james/utils/ExtendedClassLoader.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/guice-utils/src/main/java/org/apache/james/utils/ExtendedClassLoader.java
 
b/server/container/guice/guice-utils/src/main/java/org/apache/james/utils/ExtendedClassLoader.java
new file mode 100644
index 0000000..5b98666
--- /dev/null
+++ 
b/server/container/guice/guice-utils/src/main/java/org/apache/james/utils/ExtendedClassLoader.java
@@ -0,0 +1,79 @@
+/****************************************************************
+ * 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.james.utils;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.stream.Stream;
+
+import javax.inject.Inject;
+
+import org.apache.james.filesystem.api.FileSystem;
+import org.apache.james.util.StreamUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.github.fge.lambdas.Throwing;
+
+public class ExtendedClassLoader {
+
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(ExtendedClassLoader.class);
+
+    public static final String EXTENSIONS_JARS_FOLDER_NAME = 
"extensions-jars/";
+
+    private final URLClassLoader urlClassLoader;
+
+    @Inject
+    public ExtendedClassLoader(FileSystem fileSystem) {
+        this.urlClassLoader = new 
URLClassLoader(retrieveExtensionsUrls(fileSystem), getClass().getClassLoader());
+    }
+
+    private URL[] retrieveExtensionsUrls(FileSystem fileSystem) {
+        try {
+            File file = fileSystem.getFile("file://" + 
EXTENSIONS_JARS_FOLDER_NAME);
+            return recursiveExpand(file)
+                .toArray(URL[]::new);
+        } catch (IOException e) {
+            LOGGER.info("No " + EXTENSIONS_JARS_FOLDER_NAME + " folder.");
+            return new URL[]{};
+        }
+    }
+
+    private Stream<URL> recursiveExpand(File file) {
+        return StreamUtils.ofNullable(file.listFiles())
+            .flatMap(Throwing.function(this::expandFile).sneakyThrow());
+    }
+
+    private Stream<URL> expandFile(File file) throws MalformedURLException {
+        if (file.isDirectory()) {
+            return recursiveExpand(file);
+        }
+        LOGGER.info("Loading custom classpath resource {}", 
file.getAbsolutePath());
+        return Stream.of(file.toURI().toURL());
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> Class<T> locateClass(String className) throws 
ClassNotFoundException {
+        return (Class<T>) urlClassLoader.loadClass(className);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/b6fbd098/server/container/guice/mailbox/pom.xml
----------------------------------------------------------------------
diff --git a/server/container/guice/mailbox/pom.xml 
b/server/container/guice/mailbox/pom.xml
index 1e8415e..77c4183 100644
--- a/server/container/guice/mailbox/pom.xml
+++ b/server/container/guice/mailbox/pom.xml
@@ -45,6 +45,10 @@
             <artifactId>james-server-guice-configuration</artifactId>
         </dependency>
         <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>james-server-guice-utils</artifactId>
+        </dependency>
+        <dependency>
             <groupId>com.google.inject</groupId>
             <artifactId>guice</artifactId>
         </dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/b6fbd098/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/GlobalMailboxListeners.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/GlobalMailboxListeners.java
 
b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/GlobalMailboxListeners.java
index 4028383..1f51d65 100644
--- 
a/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/GlobalMailboxListeners.java
+++ 
b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/GlobalMailboxListeners.java
@@ -20,12 +20,12 @@ package org.apache.james.modules.mailbox;
 
 import java.util.List;
 
-import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.HierarchicalConfiguration;
 import org.apache.james.lifecycle.api.Configurable;
 import org.apache.james.mailbox.MailboxListener;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.store.event.MailboxListenerRegistry;
+import org.apache.james.utils.ExtendedClassLoader;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -42,19 +42,22 @@ public class GlobalMailboxListeners implements Configurable 
{
 
     private final Injector injector;
     private final MailboxListenerRegistry registry;
+    private final ExtendedClassLoader classLoader;
 
     @Inject
-    public GlobalMailboxListeners(Injector injector, MailboxListenerRegistry 
registry) {
+    public GlobalMailboxListeners(Injector injector, MailboxListenerRegistry 
registry, ExtendedClassLoader classLoader) {
         this.injector = injector;
         this.registry = registry;
+        this.classLoader = classLoader;
     }
 
     @Override
-    public void configure(HierarchicalConfiguration configuration) throws 
ConfigurationException {
+    public void configure(HierarchicalConfiguration configuration) {
         LOGGER.info("Loading mailbox listeners");
+
         List<HierarchicalConfiguration> listenersConfiguration = 
configuration.configurationsAt("listener");
-        listenersConfiguration.stream()
-            .forEach(listenerConfiguration -> 
configureListener(listenerConfiguration));
+
+        listenersConfiguration.forEach(this::configureListener);
     }
 
     @VisibleForTesting void configureListener(HierarchicalConfiguration 
configuration) {
@@ -62,16 +65,12 @@ public class GlobalMailboxListeners implements Configurable 
{
         Preconditions.checkState(!Strings.isNullOrEmpty(listenerClass), "class 
name is mandatory");
         try {
             LOGGER.info("Loading mailbox listener {}", listenerClass);
-            
registry.addGlobalListener(injector.getInstance(loadMailboxListener(listenerClass)));
-        } catch (ClassNotFoundException | InstantiationException | 
IllegalAccessException | MailboxException e) {
+            Class<MailboxListener> clazz = 
classLoader.locateClass(listenerClass);
+            MailboxListener listener = injector.getInstance(clazz);
+            registry.addGlobalListener(listener);
+        } catch (ClassNotFoundException | MailboxException e) {
             LOGGER.error("Error while loading global listener {}", 
listenerClass, e);
             Throwables.propagate(e);
         }
     }
-
-    @SuppressWarnings("unchecked")
-    private Class<MailboxListener> loadMailboxListener(String listenerClass) 
throws ClassNotFoundException, InstantiationException, IllegalAccessException {
-        Class<?> clazz = 
ClassLoader.getSystemClassLoader().loadClass(listenerClass);
-        return (Class<MailboxListener>) clazz;
-    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/b6fbd098/server/container/guice/mailbox/src/test/java/org/apache/james/modules/mailbox/GlobalMailboxListenersTest.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/mailbox/src/test/java/org/apache/james/modules/mailbox/GlobalMailboxListenersTest.java
 
b/server/container/guice/mailbox/src/test/java/org/apache/james/modules/mailbox/GlobalMailboxListenersTest.java
index 4076aac..40cd58a 100644
--- 
a/server/container/guice/mailbox/src/test/java/org/apache/james/modules/mailbox/GlobalMailboxListenersTest.java
+++ 
b/server/container/guice/mailbox/src/test/java/org/apache/james/modules/mailbox/GlobalMailboxListenersTest.java
@@ -20,13 +20,19 @@ package org.apache.james.modules.mailbox;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import java.io.ByteArrayInputStream;
+import java.io.FileNotFoundException;
 import java.nio.charset.StandardCharsets;
 
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.DefaultConfigurationBuilder;
+import org.apache.james.filesystem.api.FileSystem;
 import org.apache.james.mailbox.store.event.MailboxListenerRegistry;
+import org.apache.james.utils.ExtendedClassLoader;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -38,9 +44,14 @@ public class GlobalMailboxListenersTest {
     private GlobalMailboxListeners testee;
 
     @Before
-    public void setup() {
+    public void setup() throws Exception {
+        FileSystem fileSystem = mock(FileSystem.class);
+        when(fileSystem.getFile(anyString()))
+            .thenThrow(new FileNotFoundException());
+
         registry = new MailboxListenerRegistry();
-        testee = new GlobalMailboxListeners(Guice.createInjector(), registry);
+        testee = new GlobalMailboxListeners(Guice.createInjector(), registry,
+            new ExtendedClassLoader(fileSystem));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/james-project/blob/b6fbd098/server/container/guice/mailet/pom.xml
----------------------------------------------------------------------
diff --git a/server/container/guice/mailet/pom.xml 
b/server/container/guice/mailet/pom.xml
index 25cddf2..60daf41 100644
--- a/server/container/guice/mailet/pom.xml
+++ b/server/container/guice/mailet/pom.xml
@@ -48,6 +48,10 @@
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
+            <artifactId>james-server-guice-utils</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
             <artifactId>james-server-mailetcontainer-api</artifactId>
         </dependency>
         <dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/b6fbd098/server/container/guice/mailet/src/main/java/org/apache/james/utils/ExtendedClassLoader.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/mailet/src/main/java/org/apache/james/utils/ExtendedClassLoader.java
 
b/server/container/guice/mailet/src/main/java/org/apache/james/utils/ExtendedClassLoader.java
deleted file mode 100644
index 5b98666..0000000
--- 
a/server/container/guice/mailet/src/main/java/org/apache/james/utils/ExtendedClassLoader.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/****************************************************************
- * 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.james.utils;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.stream.Stream;
-
-import javax.inject.Inject;
-
-import org.apache.james.filesystem.api.FileSystem;
-import org.apache.james.util.StreamUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.github.fge.lambdas.Throwing;
-
-public class ExtendedClassLoader {
-
-    private static final Logger LOGGER = 
LoggerFactory.getLogger(ExtendedClassLoader.class);
-
-    public static final String EXTENSIONS_JARS_FOLDER_NAME = 
"extensions-jars/";
-
-    private final URLClassLoader urlClassLoader;
-
-    @Inject
-    public ExtendedClassLoader(FileSystem fileSystem) {
-        this.urlClassLoader = new 
URLClassLoader(retrieveExtensionsUrls(fileSystem), getClass().getClassLoader());
-    }
-
-    private URL[] retrieveExtensionsUrls(FileSystem fileSystem) {
-        try {
-            File file = fileSystem.getFile("file://" + 
EXTENSIONS_JARS_FOLDER_NAME);
-            return recursiveExpand(file)
-                .toArray(URL[]::new);
-        } catch (IOException e) {
-            LOGGER.info("No " + EXTENSIONS_JARS_FOLDER_NAME + " folder.");
-            return new URL[]{};
-        }
-    }
-
-    private Stream<URL> recursiveExpand(File file) {
-        return StreamUtils.ofNullable(file.listFiles())
-            .flatMap(Throwing.function(this::expandFile).sneakyThrow());
-    }
-
-    private Stream<URL> expandFile(File file) throws MalformedURLException {
-        if (file.isDirectory()) {
-            return recursiveExpand(file);
-        }
-        LOGGER.info("Loading custom classpath resource {}", 
file.getAbsolutePath());
-        return Stream.of(file.toURI().toURL());
-    }
-
-    @SuppressWarnings("unchecked")
-    public <T> Class<T> locateClass(String className) throws 
ClassNotFoundException {
-        return (Class<T>) urlClassLoader.loadClass(className);
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/b6fbd098/server/container/guice/pom.xml
----------------------------------------------------------------------
diff --git a/server/container/guice/pom.xml b/server/container/guice/pom.xml
index 346c5cf..ab62bb7 100644
--- a/server/container/guice/pom.xml
+++ b/server/container/guice/pom.xml
@@ -39,6 +39,7 @@
         <module>custom-mailets</module>
         <module>es-metric-reporter</module>
         <module>guice-common</module>
+        <module>guice-utils</module>
         <module>jmx</module>
         <module>jpa-common-guice</module>
         <module>jpa-guice</module>


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org
For additional commands, e-mail: server-dev-h...@james.apache.org

Reply via email to