Repository: james-project
Updated Branches:
  refs/heads/master 65f0b6383 -> 9afa62824


JAMES-1988 Add capability to load mailets from included-jars folder


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

Branch: refs/heads/master
Commit: 9afa62824fd0782a4e74b9628b696d09abfcf18a
Parents: a4f58f4
Author: benwa <btell...@linagora.com>
Authored: Mon Apr 10 11:41:35 2017 +0700
Committer: benwa <btell...@linagora.com>
Committed: Tue Apr 11 14:20:05 2017 +0700

----------------------------------------------------------------------
 .../destination/included-jars/README.md         |   5 +
 .../destination/included-jars/README.md         |   5 +
 .../jpa/destination/included-jars/README.md     |   5 +
 server/container/guice/custom-mailets/README.md |  13 ++
 server/container/guice/custom-mailets/pom.xml   | 186 +++++++++++++++++++
 .../java/com/custom/mailets/AnotherMailet.java  |  33 ++++
 .../com/custom/matchers/AnotherMatcher.java     |  36 ++++
 .../james/transport/mailets/CustomMailet.java   |  33 ++++
 .../james/transport/matchers/CustomMatcher.java |  36 ++++
 .../james/utils/GuiceProtocolHandlerLoader.java |   7 +-
 server/container/guice/mailet/pom.xml           |  30 +++
 .../apache/james/utils/ExtendedClassLoader.java |  82 ++++++++
 .../apache/james/utils/GuiceGenericLoader.java  |   9 +-
 .../apache/james/utils/GuiceMailetLoader.java   |   4 +-
 .../apache/james/utils/GuiceMatcherLoader.java  |   4 +-
 .../apache/james/utils/FileSystemFixture.java   |  82 ++++++++
 .../james/utils/GuilceMailetLoaderTest.java     | 127 +++++++++++++
 .../james/utils/GuilceMatcherLoaderTest.java    | 127 +++++++++++++
 ...uice-custom-mailets-3.0.0-beta6-SNAPSHOT.jar | Bin 0 -> 11094 bytes
 server/container/guice/pom.xml                  |   1 +
 20 files changed, 814 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/9afa6282/dockerfiles/run/guice/cassandra-ldap/destination/included-jars/README.md
----------------------------------------------------------------------
diff --git 
a/dockerfiles/run/guice/cassandra-ldap/destination/included-jars/README.md 
b/dockerfiles/run/guice/cassandra-ldap/destination/included-jars/README.md
new file mode 100644
index 0000000..1212484
--- /dev/null
+++ b/dockerfiles/run/guice/cassandra-ldap/destination/included-jars/README.md
@@ -0,0 +1,5 @@
+# Adding Jars to JAMES
+
+The jar in this folder will be added to JAMES classpath when mounted under 
/root/included-jars inside the running container.
+
+You can use it to add you customs Mailets/Matchers.

http://git-wip-us.apache.org/repos/asf/james-project/blob/9afa6282/dockerfiles/run/guice/cassandra/destination/included-jars/README.md
----------------------------------------------------------------------
diff --git 
a/dockerfiles/run/guice/cassandra/destination/included-jars/README.md 
b/dockerfiles/run/guice/cassandra/destination/included-jars/README.md
new file mode 100644
index 0000000..1212484
--- /dev/null
+++ b/dockerfiles/run/guice/cassandra/destination/included-jars/README.md
@@ -0,0 +1,5 @@
+# Adding Jars to JAMES
+
+The jar in this folder will be added to JAMES classpath when mounted under 
/root/included-jars inside the running container.
+
+You can use it to add you customs Mailets/Matchers.

http://git-wip-us.apache.org/repos/asf/james-project/blob/9afa6282/dockerfiles/run/guice/jpa/destination/included-jars/README.md
----------------------------------------------------------------------
diff --git a/dockerfiles/run/guice/jpa/destination/included-jars/README.md 
b/dockerfiles/run/guice/jpa/destination/included-jars/README.md
new file mode 100644
index 0000000..1212484
--- /dev/null
+++ b/dockerfiles/run/guice/jpa/destination/included-jars/README.md
@@ -0,0 +1,5 @@
+# Adding Jars to JAMES
+
+The jar in this folder will be added to JAMES classpath when mounted under 
/root/included-jars inside the running container.
+
+You can use it to add you customs Mailets/Matchers.

http://git-wip-us.apache.org/repos/asf/james-project/blob/9afa6282/server/container/guice/custom-mailets/README.md
----------------------------------------------------------------------
diff --git a/server/container/guice/custom-mailets/README.md 
b/server/container/guice/custom-mailets/README.md
new file mode 100644
index 0000000..bc5bc43
--- /dev/null
+++ b/server/container/guice/custom-mailets/README.md
@@ -0,0 +1,13 @@
+# How to
+
+This project is used to generate custom mailet / matcher used in unit tests of 
the underlying Guice project.
+
+This associated JAR is in the test resources.
+
+Run:
+
+```
+mvn clean install
+```
+
+And overwrite it in 
*server/container/guice/mailet/src/test/resources/recursive/extensions-jars/\*.jar*
 to update it.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/9afa6282/server/container/guice/custom-mailets/pom.xml
----------------------------------------------------------------------
diff --git a/server/container/guice/custom-mailets/pom.xml 
b/server/container/guice/custom-mailets/pom.xml
new file mode 100644
index 0000000..9364788
--- /dev/null
+++ b/server/container/guice/custom-mailets/pom.xml
@@ -0,0 +1,186 @@
+<?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";>
+    <parent>
+        <artifactId>james-server-guice</artifactId>
+        <groupId>org.apache.james</groupId>
+        <version>3.0.0-beta6-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>james-server-guice-custom-mailets</artifactId>
+
+    <name>Apache James :: Server :: Guice :: Mailet :: Custom testing 
mailets</name>
+    <description>Custom testing mailets</description>
+
+    <profiles>
+        <profile>
+            <id>disable-build-for-older-jdk</id>
+            <activation>
+                <jdk>(,1.8)</jdk>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <artifactId>maven-jar-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>default-jar</id>
+                                <phase>none</phase>
+                            </execution>
+                            <execution>
+                                <id>jar</id>
+                                <phase>none</phase>
+                            </execution>
+                            <execution>
+                                <id>test-jar</id>
+                                <phase>none</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-compiler-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>default-compile</id>
+                                <phase>none</phase>
+                            </execution>
+                            <execution>
+                                <id>default-testCompile</id>
+                                <phase>none</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>default-test</id>
+                                <phase>none</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-source-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>attach-sources</id>
+                                <phase>none</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-install-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>default-install</id>
+                                <phase>none</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-resources-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>default-resources</id>
+                                <phase>none</phase>
+                            </execution>
+                            <execution>
+                                <id>default-testResources</id>
+                                <phase>none</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-site-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>attach-descriptor</id>
+                                <phase>none</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>build-for-jdk-8</id>
+            <activation>
+                <jdk>[1.8,)</jdk>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-compiler-plugin</artifactId>
+                        <configuration>
+                            <source>1.8</source>
+                            <target>1.8</target>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+            <dependencies>
+                <dependency>
+                    <groupId>org.apache.james</groupId>
+                    <artifactId>apache-mailet-api</artifactId>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.james</groupId>
+                    <artifactId>apache-mailet-base</artifactId>
+                </dependency>
+            </dependencies>
+        </profile>
+        <profile>
+            <id>animal-sniffer-java-8</id>
+            <activation>
+                <jdk>[1.8,)</jdk>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>animal-sniffer-maven-plugin</artifactId>
+                        <configuration>
+                            <signature>
+                                <groupId>org.codehaus.mojo.signature</groupId>
+                                <artifactId>java18</artifactId>
+                                <version>1.0</version>
+                            </signature>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <id>check_java_8</id>
+                                <phase>test</phase>
+                                <goals>
+                                    <goal>check</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/9afa6282/server/container/guice/custom-mailets/src/main/java/com/custom/mailets/AnotherMailet.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/custom-mailets/src/main/java/com/custom/mailets/AnotherMailet.java
 
b/server/container/guice/custom-mailets/src/main/java/com/custom/mailets/AnotherMailet.java
new file mode 100644
index 0000000..e9d0baf
--- /dev/null
+++ 
b/server/container/guice/custom-mailets/src/main/java/com/custom/mailets/AnotherMailet.java
@@ -0,0 +1,33 @@
+/****************************************************************
+ * 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 com.custom.mailets;
+
+import javax.mail.MessagingException;
+
+import org.apache.mailet.Mail;
+import org.apache.mailet.base.GenericMailet;
+
+public class AnotherMailet extends GenericMailet {
+
+    @Override
+    public void service(Mail mail) throws MessagingException {
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/9afa6282/server/container/guice/custom-mailets/src/main/java/com/custom/matchers/AnotherMatcher.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/custom-mailets/src/main/java/com/custom/matchers/AnotherMatcher.java
 
b/server/container/guice/custom-mailets/src/main/java/com/custom/matchers/AnotherMatcher.java
new file mode 100644
index 0000000..c7acef9
--- /dev/null
+++ 
b/server/container/guice/custom-mailets/src/main/java/com/custom/matchers/AnotherMatcher.java
@@ -0,0 +1,36 @@
+/****************************************************************
+ * 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 com.custom.matchers;
+
+import java.util.Collection;
+
+import javax.mail.MessagingException;
+
+import org.apache.mailet.Mail;
+import org.apache.mailet.MailAddress;
+import org.apache.mailet.base.GenericMatcher;
+
+public class AnotherMatcher extends GenericMatcher {
+
+    @Override
+    public Collection<MailAddress> match(Mail mail) throws MessagingException {
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/9afa6282/server/container/guice/custom-mailets/src/main/java/org/apache/james/transport/mailets/CustomMailet.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/custom-mailets/src/main/java/org/apache/james/transport/mailets/CustomMailet.java
 
b/server/container/guice/custom-mailets/src/main/java/org/apache/james/transport/mailets/CustomMailet.java
new file mode 100644
index 0000000..0b4fe66
--- /dev/null
+++ 
b/server/container/guice/custom-mailets/src/main/java/org/apache/james/transport/mailets/CustomMailet.java
@@ -0,0 +1,33 @@
+/****************************************************************
+ * 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.transport.mailets;
+
+import javax.mail.MessagingException;
+
+import org.apache.mailet.Mail;
+import org.apache.mailet.base.GenericMailet;
+
+public class CustomMailet extends GenericMailet {
+
+    @Override
+    public void service(Mail mail) throws MessagingException {
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/9afa6282/server/container/guice/custom-mailets/src/main/java/org/apache/james/transport/matchers/CustomMatcher.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/custom-mailets/src/main/java/org/apache/james/transport/matchers/CustomMatcher.java
 
b/server/container/guice/custom-mailets/src/main/java/org/apache/james/transport/matchers/CustomMatcher.java
new file mode 100644
index 0000000..8c2469c
--- /dev/null
+++ 
b/server/container/guice/custom-mailets/src/main/java/org/apache/james/transport/matchers/CustomMatcher.java
@@ -0,0 +1,36 @@
+/****************************************************************
+ * 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.transport.matchers;
+
+import java.util.Collection;
+
+import javax.mail.MessagingException;
+
+import org.apache.mailet.Mail;
+import org.apache.mailet.MailAddress;
+import org.apache.mailet.base.GenericMatcher;
+
+public class CustomMatcher extends GenericMatcher {
+
+    @Override
+    public Collection<MailAddress> match(Mail mail) throws MessagingException {
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/9afa6282/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceProtocolHandlerLoader.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceProtocolHandlerLoader.java
 
b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceProtocolHandlerLoader.java
index 281f341..e4b673f 100644
--- 
a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceProtocolHandlerLoader.java
+++ 
b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceProtocolHandlerLoader.java
@@ -31,10 +31,12 @@ import com.google.inject.Injector;
 public class GuiceProtocolHandlerLoader implements ProtocolHandlerLoader {
 
     private final Injector injector;
+    private final ExtendedClassLoader extendedClassLoader;
 
     @Inject
-    public GuiceProtocolHandlerLoader(Injector injector) {
+    public GuiceProtocolHandlerLoader(Injector injector, ExtendedClassLoader 
extendedClassLoader) {
         this.injector = injector;
+        this.extendedClassLoader = extendedClassLoader;
     }
 
     @Override
@@ -50,8 +52,7 @@ public class GuiceProtocolHandlerLoader implements 
ProtocolHandlerLoader {
 
     private ProtocolHandler createProtocolHandler(String name) throws 
LoadingException {
         try {
-            @SuppressWarnings("unchecked")
-            Class<ProtocolHandler> clazz = (Class<ProtocolHandler>) 
ClassLoader.getSystemClassLoader().loadClass(name);
+            Class<ProtocolHandler> clazz = 
extendedClassLoader.locateClass(name);
             return injector.getInstance(clazz);
         } catch (ClassNotFoundException e) {
             throw new LoadingException("Can not load " + name);

http://git-wip-us.apache.org/repos/asf/james-project/blob/9afa6282/server/container/guice/mailet/pom.xml
----------------------------------------------------------------------
diff --git a/server/container/guice/mailet/pom.xml 
b/server/container/guice/mailet/pom.xml
index 33f14ec..a62da71 100644
--- a/server/container/guice/mailet/pom.xml
+++ b/server/container/guice/mailet/pom.xml
@@ -166,6 +166,14 @@
                     <artifactId>james-server-mailetcontainer-camel</artifactId>
                 </dependency>
                 <dependency>
+                    <groupId>com.github.fge</groupId>
+                    <artifactId>throwing-lambdas</artifactId>
+                </dependency>
+                <dependency>
+                    <groupId>com.github.steveash.guavate</groupId>
+                    <artifactId>guavate</artifactId>
+                </dependency>
+                <dependency>
                     <groupId>com.google.inject</groupId>
                     <artifactId>guice</artifactId>
                 </dependency>
@@ -173,6 +181,28 @@
                     <groupId>com.google.inject.extensions</groupId>
                     <artifactId>guice-multibindings</artifactId>
                 </dependency>
+                <dependency>
+                    <groupId>junit</groupId>
+                    <artifactId>junit</artifactId>
+                    <scope>test</scope>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.james</groupId>
+                    <artifactId>apache-mailet-base</artifactId>
+                    <type>test-jar</type>
+                    <scope>test</scope>
+                </dependency>
+                <dependency>
+                    <groupId>org.assertj</groupId>
+                    <artifactId>assertj-core</artifactId>
+                    <version>${assertj-3.version}</version>
+                    <scope>test</scope>
+                </dependency>
+                <dependency>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-simple</artifactId>
+                    <scope>test</scope>
+                </dependency>
             </dependencies>
         </profile>
         <profile>

http://git-wip-us.apache.org/repos/asf/james-project/blob/9afa6282/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
new file mode 100644
index 0000000..3a9baf4
--- /dev/null
+++ 
b/server/container/guice/mailet/src/main/java/org/apache/james/utils/ExtendedClassLoader.java
@@ -0,0 +1,82 @@
+/****************************************************************
+ * 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.Arrays;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import javax.inject.Inject;
+
+import org.apache.james.filesystem.api.FileSystem;
+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 Optional.ofNullable(file.listFiles())
+            .map(Arrays::stream)
+            .orElse(Stream.of())
+            .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/9afa6282/server/container/guice/mailet/src/main/java/org/apache/james/utils/GuiceGenericLoader.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/mailet/src/main/java/org/apache/james/utils/GuiceGenericLoader.java
 
b/server/container/guice/mailet/src/main/java/org/apache/james/utils/GuiceGenericLoader.java
index 645d9b0..a3f8130 100644
--- 
a/server/container/guice/mailet/src/main/java/org/apache/james/utils/GuiceGenericLoader.java
+++ 
b/server/container/guice/mailet/src/main/java/org/apache/james/utils/GuiceGenericLoader.java
@@ -22,18 +22,19 @@ package org.apache.james.utils;
 import com.google.inject.Injector;
 
 public class GuiceGenericLoader<T> {
-
     private final Injector injector;
     private final String defaultPackageName;
+    private final ExtendedClassLoader extendedClassLoader;
 
-    public GuiceGenericLoader(Injector injector, String defaultPackageName) {
+    public GuiceGenericLoader(Injector injector, ExtendedClassLoader 
extendedClassLoader, String defaultPackageName) {
         this.injector = injector;
         this.defaultPackageName = defaultPackageName;
+        this.extendedClassLoader = extendedClassLoader;
     }
 
+
     public T instanciate(String className) throws Exception {
-        @SuppressWarnings("unchecked")
-        Class<T> clazz = (Class<T>) 
ClassLoader.getSystemClassLoader().loadClass(constructFullName(className));
+        Class<T> clazz = 
extendedClassLoader.locateClass(constructFullName(className));
         return injector.getInstance(clazz);
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/9afa6282/server/container/guice/mailet/src/main/java/org/apache/james/utils/GuiceMailetLoader.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/mailet/src/main/java/org/apache/james/utils/GuiceMailetLoader.java
 
b/server/container/guice/mailet/src/main/java/org/apache/james/utils/GuiceMailetLoader.java
index f979ac2..eb0975c 100644
--- 
a/server/container/guice/mailet/src/main/java/org/apache/james/utils/GuiceMailetLoader.java
+++ 
b/server/container/guice/mailet/src/main/java/org/apache/james/utils/GuiceMailetLoader.java
@@ -35,8 +35,8 @@ public class GuiceMailetLoader implements MailetLoader {
     private final GuiceGenericLoader<Mailet> genericLoader;
 
     @Inject
-    public GuiceMailetLoader(Injector injector) {
-        this.genericLoader = new GuiceGenericLoader<>(injector, 
STANDARD_PACKAGE);
+    public GuiceMailetLoader(Injector injector, ExtendedClassLoader 
extendedClassLoader) {
+        this.genericLoader = new GuiceGenericLoader<>(injector, 
extendedClassLoader, STANDARD_PACKAGE);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/9afa6282/server/container/guice/mailet/src/main/java/org/apache/james/utils/GuiceMatcherLoader.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/mailet/src/main/java/org/apache/james/utils/GuiceMatcherLoader.java
 
b/server/container/guice/mailet/src/main/java/org/apache/james/utils/GuiceMatcherLoader.java
index 10e7cd6..db8959a 100644
--- 
a/server/container/guice/mailet/src/main/java/org/apache/james/utils/GuiceMatcherLoader.java
+++ 
b/server/container/guice/mailet/src/main/java/org/apache/james/utils/GuiceMatcherLoader.java
@@ -35,8 +35,8 @@ public class GuiceMatcherLoader implements MatcherLoader {
     private final GuiceGenericLoader<Matcher> genericLoader;
 
     @Inject
-    public GuiceMatcherLoader(Injector injector) {
-        this.genericLoader = new GuiceGenericLoader<>(injector, 
STANDARD_PACKAGE);
+    public GuiceMatcherLoader(Injector injector, ExtendedClassLoader 
extendedClassLoader) {
+        this.genericLoader = new GuiceGenericLoader<>(injector, 
extendedClassLoader, STANDARD_PACKAGE);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/9afa6282/server/container/guice/mailet/src/test/java/org/apache/james/utils/FileSystemFixture.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/mailet/src/test/java/org/apache/james/utils/FileSystemFixture.java
 
b/server/container/guice/mailet/src/test/java/org/apache/james/utils/FileSystemFixture.java
new file mode 100644
index 0000000..0731a5f
--- /dev/null
+++ 
b/server/container/guice/mailet/src/test/java/org/apache/james/utils/FileSystemFixture.java
@@ -0,0 +1,82 @@
+/****************************************************************
+ * 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.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.lang.NotImplementedException;
+import org.apache.james.filesystem.api.FileSystem;
+
+public class FileSystemFixture {
+
+    public static final FileSystem THROWING_FILE_SYSTEM = new FileSystem() {
+        @Override
+        public InputStream getResource(String url) throws IOException {
+            throw new NotImplementedException();
+        }
+
+        @Override
+        public File getFile(String fileURL) throws FileNotFoundException {
+            throw new FileNotFoundException();
+        }
+
+        @Override
+        public File getBasedir() throws FileNotFoundException {
+            throw new NotImplementedException();
+        }
+    };
+
+    public static final FileSystem CLASSPATH_FILE_SYSTEM = new FileSystem() {
+        @Override
+        public InputStream getResource(String url) throws IOException {
+            throw new NotImplementedException();
+        }
+
+        @Override
+        public File getFile(String fileURL) throws FileNotFoundException {
+            return new 
File(ClassLoader.getSystemResource("recursive/included-jars").getFile());
+        }
+
+        @Override
+        public File getBasedir() throws FileNotFoundException {
+            throw new NotImplementedException();
+        }
+    };
+
+    public static final FileSystem RECURSIVE_CLASSPATH_FILE_SYSTEM = new 
FileSystem() {
+        @Override
+        public InputStream getResource(String url) throws IOException {
+            throw new NotImplementedException();
+        }
+
+        @Override
+        public File getFile(String fileURL) throws FileNotFoundException {
+            return new 
File(ClassLoader.getSystemResource("recursive/").getFile());
+        }
+
+        @Override
+        public File getBasedir() throws FileNotFoundException {
+            throw new NotImplementedException();
+        }
+    };
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/9afa6282/server/container/guice/mailet/src/test/java/org/apache/james/utils/GuilceMailetLoaderTest.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/mailet/src/test/java/org/apache/james/utils/GuilceMailetLoaderTest.java
 
b/server/container/guice/mailet/src/test/java/org/apache/james/utils/GuilceMailetLoaderTest.java
new file mode 100644
index 0000000..6a72ce5
--- /dev/null
+++ 
b/server/container/guice/mailet/src/test/java/org/apache/james/utils/GuilceMailetLoaderTest.java
@@ -0,0 +1,127 @@
+/****************************************************************
+ * 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 static org.apache.james.utils.FileSystemFixture.CLASSPATH_FILE_SYSTEM;
+import static 
org.apache.james.utils.FileSystemFixture.RECURSIVE_CLASSPATH_FILE_SYSTEM;
+import static org.apache.james.utils.FileSystemFixture.THROWING_FILE_SYSTEM;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import javax.mail.MessagingException;
+
+import org.apache.james.transport.mailets.AddFooter;
+import org.apache.mailet.Mailet;
+import org.apache.mailet.base.test.FakeMailContext;
+import org.apache.mailet.base.test.FakeMailetConfig;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+public class GuilceMailetLoaderTest {
+
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+    private Injector injector = Guice.createInjector();
+
+    @Test
+    public void getMailetShouldLoadClass() throws Exception {
+        GuiceMailetLoader guiceMailetLoader = new GuiceMailetLoader(injector,
+            new ExtendedClassLoader(THROWING_FILE_SYSTEM));
+
+        Mailet mailet = guiceMailetLoader.getMailet(FakeMailetConfig.builder()
+            .mailetName("AddFooter")
+            .mailetContext(FakeMailContext.defaultContext())
+            .build());
+
+        assertThat(mailet).isInstanceOf(AddFooter.class);
+    }
+
+    @Test
+    public void getMailetShouldThrowOnBadType() throws Exception {
+        GuiceMailetLoader guiceMailetLoader = new GuiceMailetLoader(injector,
+            new ExtendedClassLoader(THROWING_FILE_SYSTEM));
+
+        expectedException.expect(MessagingException.class);
+
+        guiceMailetLoader.getMailet(FakeMailetConfig.builder()
+            .mailetName("org.apache.james.transport.matchers.SizeGreaterThan")
+            .mailetContext(FakeMailContext.defaultContext())
+            .build());
+    }
+
+    @Test
+    public void getMailetShouldLoadClassWhenInIncludedJars() throws Exception {
+        GuiceMailetLoader guiceMailetLoader = new GuiceMailetLoader(injector,
+            new ExtendedClassLoader(CLASSPATH_FILE_SYSTEM));
+
+        Mailet mailet = guiceMailetLoader.getMailet(FakeMailetConfig.builder()
+            .mailetName("CustomMailet")
+            .mailetContext(FakeMailContext.defaultContext())
+            .build());
+
+        assertThat(mailet.getClass().getCanonicalName())
+            .isEqualTo("org.apache.james.transport.mailets.CustomMailet");
+    }
+
+    @Test
+    public void getMailetShouldShouldRecursivelyIncludeJar() throws Exception {
+        GuiceMailetLoader guiceMailetLoader = new GuiceMailetLoader(injector,
+            new ExtendedClassLoader(RECURSIVE_CLASSPATH_FILE_SYSTEM));
+
+        Mailet mailet = guiceMailetLoader.getMailet(FakeMailetConfig.builder()
+            .mailetName("CustomMailet")
+            .mailetContext(FakeMailContext.defaultContext())
+            .build());
+
+        assertThat(mailet.getClass().getCanonicalName())
+            .isEqualTo("org.apache.james.transport.mailets.CustomMailet");
+    }
+
+    @Test
+    public void getMailedShouldShouldAllowCustomPackages() throws Exception {
+        GuiceMailetLoader guiceMailetLoader = new GuiceMailetLoader(injector,
+            new ExtendedClassLoader(CLASSPATH_FILE_SYSTEM));
+
+        Mailet mailet = guiceMailetLoader.getMailet(FakeMailetConfig.builder()
+            .mailetName("com.custom.mailets.AnotherMailet")
+            .mailetContext(FakeMailContext.defaultContext())
+            .build());
+
+        assertThat(mailet.getClass().getCanonicalName())
+            .isEqualTo("com.custom.mailets.AnotherMailet");
+    }
+
+    @Test
+    public void getMailetShouldThrowOnUnknownMailet() throws Exception {
+        GuiceMailetLoader guiceMailetLoader = new GuiceMailetLoader(injector,
+            new ExtendedClassLoader(CLASSPATH_FILE_SYSTEM));
+
+        expectedException.expect(MessagingException.class);
+
+        guiceMailetLoader.getMailet(FakeMailetConfig.builder()
+            .mailetName("org.apache.james.transport.mailets.Unknown")
+            .mailetContext(FakeMailContext.defaultContext())
+            .build());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/9afa6282/server/container/guice/mailet/src/test/java/org/apache/james/utils/GuilceMatcherLoaderTest.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/mailet/src/test/java/org/apache/james/utils/GuilceMatcherLoaderTest.java
 
b/server/container/guice/mailet/src/test/java/org/apache/james/utils/GuilceMatcherLoaderTest.java
new file mode 100644
index 0000000..bd8c7c3
--- /dev/null
+++ 
b/server/container/guice/mailet/src/test/java/org/apache/james/utils/GuilceMatcherLoaderTest.java
@@ -0,0 +1,127 @@
+/****************************************************************
+ * 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 static org.apache.james.utils.FileSystemFixture.CLASSPATH_FILE_SYSTEM;
+import static 
org.apache.james.utils.FileSystemFixture.RECURSIVE_CLASSPATH_FILE_SYSTEM;
+import static org.apache.james.utils.FileSystemFixture.THROWING_FILE_SYSTEM;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import javax.mail.MessagingException;
+
+import org.apache.james.transport.matchers.All;
+import org.apache.mailet.Matcher;
+import org.apache.mailet.base.test.FakeMailContext;
+import org.apache.mailet.base.test.FakeMatcherConfig;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+public class GuilceMatcherLoaderTest {
+
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+    private Injector injector = Guice.createInjector();
+
+    @Test
+    public void getMatcherShouldLoadClass() throws Exception {
+        GuiceMatcherLoader guiceMailetLoader = new GuiceMatcherLoader(injector,
+            new ExtendedClassLoader(THROWING_FILE_SYSTEM));
+
+        Matcher matcher = 
guiceMailetLoader.getMatcher(FakeMatcherConfig.builder()
+            .matcherName("All")
+            .mailetContext(FakeMailContext.defaultContext())
+            .build());
+
+        assertThat(matcher).isInstanceOf(All.class);
+    }
+
+    @Test
+    public void getMatcherShouldThrowOnBadType() throws Exception {
+        GuiceMatcherLoader guiceMatcherLoader = new 
GuiceMatcherLoader(injector,
+            new ExtendedClassLoader(THROWING_FILE_SYSTEM));
+
+        expectedException.expect(MessagingException.class);
+
+        guiceMatcherLoader.getMatcher(FakeMatcherConfig.builder()
+            .matcherName("org.apache.james.transport.mailets.Null")
+            .mailetContext(FakeMailContext.defaultContext())
+            .build());
+    }
+
+    @Test
+    public void getMatcherShouldLoadClassWhenInIncludedJars() throws Exception 
{
+        GuiceMatcherLoader guiceMatcherLoader = new 
GuiceMatcherLoader(injector,
+            new ExtendedClassLoader(CLASSPATH_FILE_SYSTEM));
+
+        Matcher matcher = 
guiceMatcherLoader.getMatcher(FakeMatcherConfig.builder()
+            .matcherName("CustomMatcher")
+            .mailetContext(FakeMailContext.defaultContext())
+            .build());
+
+        assertThat(matcher.getClass().getCanonicalName())
+            .isEqualTo("org.apache.james.transport.matchers.CustomMatcher");
+    }
+
+    @Test
+    public void getMatcherShouldShouldRecursivelyIncludeJar() throws Exception 
{
+        GuiceMatcherLoader guiceMatcherLoader = new 
GuiceMatcherLoader(injector,
+            new ExtendedClassLoader(RECURSIVE_CLASSPATH_FILE_SYSTEM));
+
+        Matcher matcher = 
guiceMatcherLoader.getMatcher(FakeMatcherConfig.builder()
+            .matcherName("CustomMatcher")
+            .mailetContext(FakeMailContext.defaultContext())
+            .build());
+
+        assertThat(matcher.getClass().getCanonicalName())
+            .isEqualTo("org.apache.james.transport.matchers.CustomMatcher");
+    }
+
+    @Test
+    public void getMatcherShouldAllowCustomPackages() throws Exception {
+        GuiceMatcherLoader guiceMatcherLoader = new 
GuiceMatcherLoader(injector,
+            new ExtendedClassLoader(RECURSIVE_CLASSPATH_FILE_SYSTEM));
+
+        Matcher matcher = 
guiceMatcherLoader.getMatcher(FakeMatcherConfig.builder()
+            .matcherName("com.custom.matchers.AnotherMatcher")
+            .mailetContext(FakeMailContext.defaultContext())
+            .build());
+
+        assertThat(matcher.getClass().getCanonicalName())
+            .isEqualTo("com.custom.matchers.AnotherMatcher");
+    }
+
+    @Test
+    public void getMatcherShouldThrowOnUnknownMailet() throws Exception {
+        GuiceMatcherLoader guiceMatcherLoader = new 
GuiceMatcherLoader(injector,
+            new ExtendedClassLoader(CLASSPATH_FILE_SYSTEM));
+
+        expectedException.expect(MessagingException.class);
+
+        guiceMatcherLoader.getMatcher(FakeMatcherConfig.builder()
+            .matcherName("org.apache.james.transport.matchers.Unknown")
+            .mailetContext(FakeMailContext.defaultContext())
+            .build());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/9afa6282/server/container/guice/mailet/src/test/resources/recursive/included-jars/james-server-guice-custom-mailets-3.0.0-beta6-SNAPSHOT.jar
----------------------------------------------------------------------
diff --git 
a/server/container/guice/mailet/src/test/resources/recursive/included-jars/james-server-guice-custom-mailets-3.0.0-beta6-SNAPSHOT.jar
 
b/server/container/guice/mailet/src/test/resources/recursive/included-jars/james-server-guice-custom-mailets-3.0.0-beta6-SNAPSHOT.jar
new file mode 100644
index 0000000..3e31ff3
Binary files /dev/null and 
b/server/container/guice/mailet/src/test/resources/recursive/included-jars/james-server-guice-custom-mailets-3.0.0-beta6-SNAPSHOT.jar
 differ

http://git-wip-us.apache.org/repos/asf/james-project/blob/9afa6282/server/container/guice/pom.xml
----------------------------------------------------------------------
diff --git a/server/container/guice/pom.xml b/server/container/guice/pom.xml
index 1d7a263..0b66889 100644
--- a/server/container/guice/pom.xml
+++ b/server/container/guice/pom.xml
@@ -118,6 +118,7 @@
         <module>guice-common</module>
         <module>cassandra-guice</module>
         <module>cassandra-ldap-guice</module>
+        <module>custom-mailets</module>
         <module>mailbox</module>
         <module>mailet</module>
         <module>memory-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