You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ud...@apache.org on 2020/07/02 18:10:46 UTC
[geode] 10/29: GEODE-8043 - Create JBossModuleService and implement
loadModule. (#5081)
This is an automated email from the ASF dual-hosted git repository.
udo pushed a commit to branch feature/GEODE-8294
in repository https://gitbox.apache.org/repos/asf/geode.git
commit 6a65bd359d7614e319f1e188a04b6f2d3c81aa5b
Author: Udo Kohlmeyer <uk...@pivtotal.io>
AuthorDate: Tue May 19 09:20:46 2020 -0700
GEODE-8043 - Create JBossModuleService and implement loadModule. (#5081)
---
.../src/test/resources/expected-pom.xml | 18 +
.../gradle/plugins/DependencyConstraints.groovy | 3 +
geode-assembly/build.gradle | 2 +
.../integrationTest/resources/assembly_content.txt | 22 ++
.../resources/dependency_classpath.txt | 27 +-
.../integrationTest/resources/expected_jars.txt | 1 +
geode-common-services/build.gradle | 33 ++
.../geode/services/module/ModuleDescriptor.java | 100 +++++
.../geode/services/module/ModuleService.java | 36 ++
.../src/test/resources/expected-pom.xml | 60 +++
geode-modules/build.gradle | 97 +++++
.../services/module/impl/GeodeModuleLoader.java | 53 +++
.../services/module/impl/JBossModuleService.java | 115 ++++++
.../module/impl/JBossModuleServiceTest.java | 402 +++++++++++++++++++++
geode-modules/src/test/resources/expected-pom.xml | 80 ++++
.../module1/java/org/apache/geode/Module1.java | 19 +
.../module2/java/org.apache.geode/Module2.java | 19 +
.../module3/java/org/apache/geode/Module3.java | 19 +
.../module4/java/org/apache/geode/Module4.java | 19 +
settings.gradle | 2 +
20 files changed, 1115 insertions(+), 12 deletions(-)
diff --git a/boms/geode-all-bom/src/test/resources/expected-pom.xml b/boms/geode-all-bom/src/test/resources/expected-pom.xml
index 2885bd8..3807199 100644
--- a/boms/geode-all-bom/src/test/resources/expected-pom.xml
+++ b/boms/geode-all-bom/src/test/resources/expected-pom.xml
@@ -464,6 +464,12 @@
<scope>compile</scope>
</dependency>
<dependency>
+ <groupId>org.jboss.modules</groupId>
+ <artifactId>jboss-modules</artifactId>
+ <version>1.10.1.Final</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
<groupId>org.jgroups</groupId>
<artifactId>jgroups</artifactId>
<version>3.6.14.Final</version>
@@ -891,6 +897,12 @@
</dependency>
<dependency>
<groupId>org.apache.geode</groupId>
+ <artifactId>geode-common-services</artifactId>
+ <version>${version}</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
<artifactId>geode-concurrency-test</artifactId>
<version>${version}</version>
<scope>compile</scope>
@@ -981,6 +993,12 @@
</dependency>
<dependency>
<groupId>org.apache.geode</groupId>
+ <artifactId>geode-modules</artifactId>
+ <version>${version}</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
<artifactId>geode-old-client-support</artifactId>
<version>${version}</version>
<scope>compile</scope>
diff --git a/buildSrc/src/main/groovy/org/apache/geode/gradle/plugins/DependencyConstraints.groovy b/buildSrc/src/main/groovy/org/apache/geode/gradle/plugins/DependencyConstraints.groovy
index 14d6b034..bb3ea96 100644
--- a/buildSrc/src/main/groovy/org/apache/geode/gradle/plugins/DependencyConstraints.groovy
+++ b/buildSrc/src/main/groovy/org/apache/geode/gradle/plugins/DependencyConstraints.groovy
@@ -31,6 +31,8 @@ class DependencyConstraints implements Plugin<Project> {
Map<String,String> deps = new HashMap<>()
// These versions are consumed beyond the scope of source set dependencies.
+ deps.put("jboss-modules.version", "1.10.1.Final")
+
// These version numbers are consumed by :geode-modules-assembly:distAppServer filtering
// Some of these are referenced below as well
deps.put("antlr.version", "2.7.7")
@@ -155,6 +157,7 @@ class DependencyConstraints implements Plugin<Project> {
api(group: 'org.eclipse.persistence', name: 'javax.persistence', version: '2.2.1')
api(group: 'org.httpunit', name: 'httpunit', version: '1.7.3')
api(group: 'org.iq80.snappy', name: 'snappy', version: '0.4')
+ api(group: 'org.jboss.modules', name: 'jboss-modules', version: get('jboss-modules.version'))
api(group: 'org.jgroups', name: 'jgroups', version: get('jgroups.version'))
api(group: 'org.mockito', name: 'mockito-core', version: '3.3.3')
api(group: 'org.mortbay.jetty', name: 'servlet-api', version: '3.0.20100224')
diff --git a/geode-assembly/build.gradle b/geode-assembly/build.gradle
index 9f2e7f3..134cbe7 100755
--- a/geode-assembly/build.gradle
+++ b/geode-assembly/build.gradle
@@ -28,6 +28,7 @@ import java.nio.file.Paths
// This list is used in a loop to defined the /lib copySpec
def dependentProjectNames = [
':geode-common',
+ ':geode-common-services',
':geode-connectors',
':geode-core',
':geode-cq',
@@ -36,6 +37,7 @@ def dependentProjectNames = [
':geode-logging',
':geode-lucene',
':geode-memcached',
+ ':geode-modules',
':geode-old-client-support',
':geode-protobuf',
':geode-protobuf-messages',
diff --git a/geode-assembly/src/integrationTest/resources/assembly_content.txt b/geode-assembly/src/integrationTest/resources/assembly_content.txt
index bec9cce..60c602b 100644
--- a/geode-assembly/src/integrationTest/resources/assembly_content.txt
+++ b/geode-assembly/src/integrationTest/resources/assembly_content.txt
@@ -963,6 +963,25 @@ javadoc/org/apache/geode/security/SecurityManager.html
javadoc/org/apache/geode/security/package-frame.html
javadoc/org/apache/geode/security/package-summary.html
javadoc/org/apache/geode/security/package-tree.html
+javadoc/org/apache/geode/services/bootstrapping/BootstrappingService.html
+javadoc/org/apache/geode/services/bootstrapping/package-frame.html
+javadoc/org/apache/geode/services/bootstrapping/package-summary.html
+javadoc/org/apache/geode/services/bootstrapping/package-tree.html
+javadoc/org/apache/geode/services/management/ManagementService.html
+javadoc/org/apache/geode/services/management/package-frame.html
+javadoc/org/apache/geode/services/management/package-summary.html
+javadoc/org/apache/geode/services/management/package-tree.html
+javadoc/org/apache/geode/services/module/ModuleDescriptor.Builder.html
+javadoc/org/apache/geode/services/module/ModuleDescriptor.html
+javadoc/org/apache/geode/services/module/ModuleService.html
+javadoc/org/apache/geode/services/module/impl/GeodeModuleLoader.html
+javadoc/org/apache/geode/services/module/impl/JBossModuleService.html
+javadoc/org/apache/geode/services/module/impl/package-frame.html
+javadoc/org/apache/geode/services/module/impl/package-summary.html
+javadoc/org/apache/geode/services/module/impl/package-tree.html
+javadoc/org/apache/geode/services/module/package-frame.html
+javadoc/org/apache/geode/services/module/package-summary.html
+javadoc/org/apache/geode/services/module/package-tree.html
javadoc/overview-frame.html
javadoc/overview-summary.html
javadoc/overview-tree.html
@@ -988,6 +1007,7 @@ lib/fastutil-8.3.1.jar
lib/findbugs-annotations-1.3.9-1.jar
lib/geo-0.7.7.jar
lib/geode-common-0.0.0.jar
+lib/geode-common-services-0.0.0.jar
lib/geode-connectors-0.0.0.jar
lib/geode-core-0.0.0.jar
lib/geode-cq-0.0.0.jar
@@ -1001,6 +1021,7 @@ lib/geode-lucene-0.0.0.jar
lib/geode-management-0.0.0.jar
lib/geode-membership-0.0.0.jar
lib/geode-memcached-0.0.0.jar
+lib/geode-modules-0.0.0.jar
lib/geode-old-client-support-0.0.0.jar
lib/geode-protobuf-0.0.0.jar
lib/geode-protobuf-messages-0.0.0.jar
@@ -1025,6 +1046,7 @@ lib/javax.servlet-api-3.1.0.jar
lib/javax.transaction-api-1.3.jar
lib/jaxb-api-2.3.1.jar
lib/jaxb-impl-2.3.2.jar
+lib/jboss-modules-1.10.1.Final.jar
lib/jetty-http-9.4.21.v20190926.jar
lib/jetty-io-9.4.21.v20190926.jar
lib/jetty-security-9.4.21.v20190926.jar
diff --git a/geode-assembly/src/integrationTest/resources/dependency_classpath.txt b/geode-assembly/src/integrationTest/resources/dependency_classpath.txt
index df1bad5..078da56 100644
--- a/geode-assembly/src/integrationTest/resources/dependency_classpath.txt
+++ b/geode-assembly/src/integrationTest/resources/dependency_classpath.txt
@@ -1,4 +1,5 @@
geode-common-0.0.0.jar
+geode-common-services-0.0.0.jar
geode-connectors-0.0.0.jar
geode-core-0.0.0.jar
geode-cq-0.0.0.jar
@@ -6,8 +7,8 @@ geode-gfsh-0.0.0.jar
geode-log4j-0.0.0.jar
geode-logging-0.0.0.jar
geode-lucene-0.0.0.jar
-geode-management-0.0.0.jar
geode-memcached-0.0.0.jar
+geode-modules-0.0.0.jar
geode-old-client-support-0.0.0.jar
geode-protobuf-0.0.0.jar
geode-protobuf-messages-0.0.0.jar
@@ -16,22 +17,15 @@ geode-redis-0.0.0.jar
geode-serialization-0.0.0.jar
geode-tcp-server-0.0.0.jar
geode-wan-0.0.0.jar
+geode-management-0.0.0.jar
jackson-databind-2.10.1.jar
jackson-annotations-2.10.1.jar
jackson-core-2.10.1.jar
geode-membership-0.0.0.jar
geode-http-service-0.0.0.jar
geode-unsafe-0.0.0.jar
-httpclient-4.5.12.jar
-httpcore-4.4.13.jar
-HikariCP-3.4.2.jar
-commons-lang3-3.10.jar
-jaxb-api-2.3.1.jar
-log4j-jcl-2.13.1.jar
-log4j-api-2.13.1.jar
-spring-shell-1.2.0.RELEASE.jar
-rmiio-2.1.2.jar
antlr-2.7.7.jar
+rmiio-2.1.2.jar
javax.activation-1.2.0.jar
istack-commons-runtime-3.0.11.jar
jaxb-impl-2.3.2.jar
@@ -39,6 +33,7 @@ commons-validator-1.6.jar
shiro-core-1.5.2.jar
shiro-config-ogdl-1.5.2.jar
commons-beanutils-1.9.4.jar
+httpclient-4.5.12.jar
commons-codec-1.14.jar
commons-collections-3.2.2.jar
commons-io-2.6.jar
@@ -53,9 +48,12 @@ jetty-servlet-9.4.21.v20190926.jar
jetty-security-9.4.21.v20190926.jar
jetty-server-9.4.21.v20190926.jar
javax.servlet-api-3.1.0.jar
+jaxb-api-2.3.1.jar
jna-platform-5.5.0.jar
jna-5.5.0.jar
jopt-simple-5.0.4.jar
+commons-lang3-3.10.jar
+httpcore-4.4.13.jar
snappy-0.4.jar
jgroups-3.6.14.Final.jar
shiro-cache-1.5.2.jar
@@ -66,17 +64,21 @@ shiro-event-1.5.2.jar
shiro-crypto-core-1.5.2.jar
shiro-lang-1.5.2.jar
slf4j-api-1.7.30.jar
+log4j-api-2.13.1.jar
spring-core-5.2.5.RELEASE.jar
-javax.activation-api-1.2.0.jar
-jline-2.12.jar
HdrHistogram-2.1.12.jar
LatencyUtils-2.0.3.jar
javax.transaction-api-1.3.jar
+javax.activation-api-1.2.0.jar
spring-jcl-5.2.5.RELEASE.jar
jetty-http-9.4.21.v20190926.jar
jetty-io-9.4.21.v20190926.jar
jetty-xml-9.4.21.v20190926.jar
jetty-util-9.4.21.v20190926.jar
+HikariCP-3.4.2.jar
+log4j-jcl-2.13.1.jar
+spring-shell-1.2.0.RELEASE.jar
+jline-2.12.jar
log4j-slf4j-impl-2.13.1.jar
log4j-core-2.13.1.jar
log4j-jul-2.13.1.jar
@@ -85,6 +87,7 @@ lucene-analyzers-common-6.6.6.jar
lucene-queryparser-6.6.6.jar
lucene-core-6.6.6.jar
lucene-queries-6.6.6.jar
+jboss-modules-1.10.1.Final.jar
protobuf-java-3.11.4.jar
geo-0.7.7.jar
netty-all-4.1.48.Final.jar
diff --git a/geode-assembly/src/integrationTest/resources/expected_jars.txt b/geode-assembly/src/integrationTest/resources/expected_jars.txt
index c116f7c..131d9a1 100644
--- a/geode-assembly/src/integrationTest/resources/expected_jars.txt
+++ b/geode-assembly/src/integrationTest/resources/expected_jars.txt
@@ -44,6 +44,7 @@ javax.servlet-api
javax.transaction-api
jaxb-api
jaxb-impl
+jboss-modules
jcip-annotations
jetty-http
jetty-io
diff --git a/geode-common-services/build.gradle b/geode-common-services/build.gradle
new file mode 100644
index 0000000..da983cf
--- /dev/null
+++ b/geode-common-services/build.gradle
@@ -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.
+ */
+
+apply from: "${rootDir}/${scriptDir}/standard-subproject-configuration.gradle"
+
+apply from: "${project.projectDir}/../gradle/publish-java.gradle"
+apply from: "${project.projectDir}/../gradle/warnings.gradle"
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ compile(platform(project(':boms:geode-all-bom')))
+
+ compile(project(':geode-common'))
+
+ compile(project(':geode-core'))
+}
diff --git a/geode-common-services/src/main/java/org/apache/geode/services/module/ModuleDescriptor.java b/geode-common-services/src/main/java/org/apache/geode/services/module/ModuleDescriptor.java
new file mode 100644
index 0000000..3b84130
--- /dev/null
+++ b/geode-common-services/src/main/java/org/apache/geode/services/module/ModuleDescriptor.java
@@ -0,0 +1,100 @@
+/*
+ * 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.geode.services.module;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.geode.annotations.Experimental;
+
+/**
+ * Holds information to describe a classloader-isolated module including how to create it.
+ *
+ * @see Builder
+ * @see ModuleService
+ *
+ * @since Geode 1.13.0
+ */
+@Experimental
+public class ModuleDescriptor {
+
+ private String name;
+
+ private String version;
+
+ private List<String> sources;
+
+ private List<String> dependencies;
+
+ private ModuleDescriptor(String name, String version, List<String> sources,
+ List<String> dependencies) {
+ this.name = name;
+ this.version = version;
+ this.sources = sources;
+ this.dependencies = dependencies;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public List<String> getSources() {
+ return sources;
+ }
+
+ public List<String> getDependedOnModules() {
+ return dependencies;
+ }
+
+ public String getVersionedName() {
+ return name + ":" + version;
+ }
+
+ /**
+ * A Builder used to construct a {@link ModuleDescriptor}
+ */
+ public static class Builder {
+
+ private final String name;
+ private final String version;
+ private List<String> dependencies = Collections.emptyList();
+ private List<String> sources = Collections.emptyList();
+
+ public Builder(String name, String version) {
+ this.name = name;
+ this.version = version;
+ }
+
+ public Builder fromSources(String... sources) {
+ this.sources = Arrays.asList(sources);
+ return this;
+ }
+
+ public Builder dependsOnModules(String... dependencies) {
+ this.dependencies = Arrays.asList(dependencies);
+ return this;
+ }
+
+ public ModuleDescriptor build() {
+ return new ModuleDescriptor(name, version, sources, dependencies);
+ }
+ }
+}
diff --git a/geode-common-services/src/main/java/org/apache/geode/services/module/ModuleService.java b/geode-common-services/src/main/java/org/apache/geode/services/module/ModuleService.java
new file mode 100644
index 0000000..cd295c0
--- /dev/null
+++ b/geode-common-services/src/main/java/org/apache/geode/services/module/ModuleService.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.geode.services.module;
+
+import org.apache.geode.annotations.Experimental;
+
+/**
+ * Loads and unloads modules and services in a classloader-isolated manner.
+ *
+ * @since Geode 1.13.0
+ */
+@Experimental
+public interface ModuleService {
+
+ /**
+ * Loads a module from a resource.
+ *
+ * @param moduleDescriptor description of the module to be loaded and information necessary to
+ * load it.
+ * @return true on success, false if the module could not be loaded.
+ */
+ boolean loadModule(ModuleDescriptor moduleDescriptor);
+}
diff --git a/geode-common-services/src/test/resources/expected-pom.xml b/geode-common-services/src/test/resources/expected-pom.xml
new file mode 100644
index 0000000..26f1cdd
--- /dev/null
+++ b/geode-common-services/src/test/resources/expected-pom.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+ <!--
+ 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.
+ -->
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-common-services</artifactId>
+ <version>1.13.0-SNAPSHOT</version>
+ <name>Apache Geode</name>
+ <description>Apache Geode provides a database-like consistency model, reliable transaction processing and a shared-nothing architecture to maintain very low latency performance with high concurrency processing</description>
+ <url>http://geode.apache.org</url>
+ <licenses>
+ <license>
+ <name>The Apache Software License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+ </license>
+ </licenses>
+ <scm>
+ <connection>scm:git:https://github.com:apache/geode.git</connection>
+ <developerConnection>scm:git:https://github.com:apache/geode.git</developerConnection>
+ <url>https://github.com/apache/geode</url>
+ </scm>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-all-bom</artifactId>
+ <version>1.13.0-SNAPSHOT</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-common</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-core</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/geode-modules/build.gradle b/geode-modules/build.gradle
new file mode 100644
index 0000000..319c0bd
--- /dev/null
+++ b/geode-modules/build.gradle
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+apply from: "${rootDir}/${scriptDir}/standard-subproject-configuration.gradle"
+
+apply from: "${project.projectDir}/../gradle/publish-java.gradle"
+apply from: "${project.projectDir}/../gradle/warnings.gradle"
+
+sourceSets {
+ module1 {
+ java.srcDir "src/testModules/module1/java"
+ resources.srcDir "src/testModules/module1/resources"
+ compileClasspath += configurations.compileClasspath
+ runtimeClasspath += configurations.runtimeClasspath
+ }
+ module2 {
+ java.srcDir "src/testModules/module2/java"
+ resources.srcDir "src/testModules/module2/resources"
+ compileClasspath += configurations.compileClasspath
+ runtimeClasspath += configurations.runtimeClasspath
+ }
+ module3 {
+ java.srcDir "src/testModules/module3/java"
+ resources.srcDir "src/testModules/module3/resources"
+ compileClasspath += configurations.compileClasspath
+ runtimeClasspath += configurations.runtimeClasspath
+ }
+ module4 {
+ java.srcDir "src/testModules/module4/java"
+ resources.srcDir "src/testModules/module4/resources"
+ compileClasspath += configurations.compileClasspath
+ runtimeClasspath += configurations.runtimeClasspath
+ }
+}
+
+task module1Jar(type: Jar, dependsOn: classes) {
+ description 'Assembles the jar archive that contains the module1 classes'
+ from sourceSets.module1.output
+ archiveName 'module1.jar'
+}
+
+task module2Jar(type: Jar, dependsOn: classes) {
+ description 'Assembles the jar archive that contains the module2 classes'
+ from sourceSets.module2.output
+ archiveName 'module2.jar'
+}
+
+task module3Jar(type: Jar, dependsOn: classes) {
+ description 'Assembles the jar archive that contains the module3 classes'
+ from sourceSets.module3.output
+ archiveName 'module3.jar'
+}
+
+task module4Jar(type: Jar, dependsOn: classes) {
+ description 'Assembles the jar archive that contains the module4 classes'
+ from sourceSets.module4.output
+ archiveName 'module4.jar'
+}
+
+tasks.test.dependsOn("module1Jar")
+tasks.test.dependsOn("module2Jar")
+tasks.test.dependsOn("module3Jar")
+tasks.test.dependsOn("module4Jar")
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testCompile(group: 'junit', name: 'junit', version: '4.12')
+ testImplementation('org.assertj:assertj-core')
+
+ compile(platform(project(':boms:geode-all-bom')))
+
+ compile(project(':geode-common'))
+ implementation(project(':geode-logging'))
+ implementation(project(':geode-log4j'))
+
+ compile(project(':geode-common-services'))
+
+ implementation('org.apache.logging.log4j:log4j-core')
+ compile('org.jboss.modules:jboss-modules')
+}
diff --git a/geode-modules/src/main/java/org/apache/geode/services/module/impl/GeodeModuleLoader.java b/geode-modules/src/main/java/org/apache/geode/services/module/impl/GeodeModuleLoader.java
new file mode 100644
index 0000000..913df0c
--- /dev/null
+++ b/geode-modules/src/main/java/org/apache/geode/services/module/impl/GeodeModuleLoader.java
@@ -0,0 +1,53 @@
+/*
+ * 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.geode.services.module.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jboss.modules.DelegatingModuleLoader;
+import org.jboss.modules.Module;
+import org.jboss.modules.ModuleLoadException;
+import org.jboss.modules.ModuleLoader;
+import org.jboss.modules.ModuleSpec;
+
+import org.apache.geode.annotations.Experimental;
+
+/**
+ * {@link ModuleLoader} for use by {@link JBossModuleService}.
+ */
+@Experimental
+public class GeodeModuleLoader extends DelegatingModuleLoader {
+ private Map<String, ModuleSpec> moduleSpecs = new HashMap<>();
+
+ public GeodeModuleLoader() {
+ super(Module.getSystemModuleLoader(), ModuleLoader.NO_FINDERS);
+ }
+
+ public void addModuleSpec(ModuleSpec moduleSpec) {
+ moduleSpecs.put(moduleSpec.getName(), moduleSpec);
+ }
+
+ @Override
+ protected ModuleSpec findModule(String name) throws ModuleLoadException {
+ ModuleSpec moduleSpec = moduleSpecs.get(name);
+ if (moduleSpec == null) {
+ throw new ModuleLoadException(
+ String.format("ModuleSpec for Module %s could not be found", name));
+ }
+ return moduleSpecs.get(name);
+ }
+}
diff --git a/geode-modules/src/main/java/org/apache/geode/services/module/impl/JBossModuleService.java b/geode-modules/src/main/java/org/apache/geode/services/module/impl/JBossModuleService.java
new file mode 100644
index 0000000..9715709
--- /dev/null
+++ b/geode-modules/src/main/java/org/apache/geode/services/module/impl/JBossModuleService.java
@@ -0,0 +1,115 @@
+/*
+ * 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.geode.services.module.impl;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.JarFile;
+
+import org.apache.logging.log4j.Logger;
+import org.jboss.modules.LocalDependencySpecBuilder;
+import org.jboss.modules.Module;
+import org.jboss.modules.ModuleDependencySpecBuilder;
+import org.jboss.modules.ModuleLoadException;
+import org.jboss.modules.ModuleSpec;
+import org.jboss.modules.ResourceLoader;
+import org.jboss.modules.ResourceLoaderSpec;
+import org.jboss.modules.ResourceLoaders;
+import org.jboss.modules.Version;
+
+import org.apache.geode.annotations.Experimental;
+import org.apache.geode.logging.internal.log4j.api.LogService;
+import org.apache.geode.services.module.ModuleDescriptor;
+import org.apache.geode.services.module.ModuleService;
+
+/**
+ * Implementation of {@link ModuleService} using JBoss-Modules.
+ */
+@Experimental
+public class JBossModuleService implements ModuleService {
+
+ private final Map<String, Module> modules = new HashMap<>();
+
+ private final GeodeModuleLoader moduleLoader = new GeodeModuleLoader();
+
+ private final Logger logger;
+
+ public JBossModuleService() {
+ this(LogService.getLogger());
+ }
+
+ public JBossModuleService(Logger logger) {
+ this.logger = logger;
+ }
+
+ public Module getModule(String name) {
+ return modules.get(name);
+ }
+
+ @Override
+ public boolean loadModule(ModuleDescriptor moduleDescriptor) {
+ logger.debug(String.format("Beginning to load module %s", moduleDescriptor.getVersionedName()));
+
+ if (modules.containsKey(moduleDescriptor.getVersionedName())) {
+ logger
+ .warn(String.format("Module %s is already loaded.", moduleDescriptor.getVersionedName()));
+ return false;
+ }
+
+ ModuleSpec.Builder builder = ModuleSpec.build(moduleDescriptor.getVersionedName());
+ builder.setVersion(Version.parse(moduleDescriptor.getVersion()));
+ builder.addDependency(new LocalDependencySpecBuilder()
+ .setImportServices(true)
+ .setExport(true)
+ .build());
+
+ moduleDescriptor.getDependedOnModules().forEach(dependency -> {
+ logger.debug(String.format("Adding dependency on module %s", dependency));
+ builder.addDependency(new ModuleDependencySpecBuilder()
+ .setName(dependency)
+ .build());
+ });
+
+ try {
+ for (String source : moduleDescriptor.getSources()) {
+ logger.debug(String.format("Adding resource %s to module", source));
+ ResourceLoader resourceLoader =
+ ResourceLoaders.createJarResourceLoader(new JarFile(source));
+ builder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec(resourceLoader));
+ }
+ } catch (IOException e) {
+ logger.error(e);
+ return false;
+ }
+
+ ModuleSpec moduleSpec = builder.create();
+ moduleLoader.addModuleSpec(moduleSpec);
+
+ try {
+ modules.put(moduleDescriptor.getVersionedName(),
+ moduleLoader.loadModule(moduleSpec.getName()));
+ } catch (ModuleLoadException e) {
+ logger.error(e);
+ return false;
+ }
+
+ logger
+ .debug(String.format("Module %s successfully loaded", moduleDescriptor.getVersionedName()));
+
+ return true;
+ }
+}
diff --git a/geode-modules/src/test/java/org/apache/geode/services/module/impl/JBossModuleServiceTest.java b/geode-modules/src/test/java/org/apache/geode/services/module/impl/JBossModuleServiceTest.java
new file mode 100644
index 0000000..bca62af
--- /dev/null
+++ b/geode-modules/src/test/java/org/apache/geode/services/module/impl/JBossModuleServiceTest.java
@@ -0,0 +1,402 @@
+/*
+ * 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.geode.services.module.impl;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.jboss.modules.Module;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.geode.services.module.ModuleDescriptor;
+
+public class JBossModuleServiceTest {
+
+ private static final String MODULE1_PATH =
+ System.getProperty("user.dir") + "/../libs/module1.jar";
+ private static final String MODULE2_PATH =
+ System.getProperty("user.dir") + "/../libs/module2.jar";
+ private static final String MODULE3_PATH =
+ System.getProperty("user.dir") + "/../libs/module3.jar";
+ private static final String MODULE4_PATH =
+ System.getProperty("user.dir") + "/../libs/module4.jar";
+
+ private JBossModuleService moduleService;
+
+ @Before
+ public void setup() {
+ moduleService = new JBossModuleService();
+ }
+
+ @After
+ public void teardown() {
+ moduleService = null;
+ }
+
+ @Test
+ public void modulesNotAccessibleFromSystemClassloaderNoModulesLoaded() {
+ assertThatThrownBy(() -> {
+ this.getClass().getClassLoader().loadClass("org.apache.geode.Module1");
+ }).isInstanceOf(ClassNotFoundException.class);
+
+ assertThatThrownBy(() -> {
+ this.getClass().getClassLoader().loadClass("org.apache.geode.Module2");
+ }).isInstanceOf(ClassNotFoundException.class);
+ }
+
+ @Test
+ public void modulesNotAccessibleFromSystemClassloaderWithModulesLoaded() {
+ ModuleDescriptor module1Descriptor = new ModuleDescriptor.Builder("module1", "1.0")
+ .fromSources(MODULE1_PATH)
+ .build();
+ ModuleDescriptor module2Descriptor = new ModuleDescriptor.Builder("module2", "1.0")
+ .fromSources(MODULE2_PATH)
+ .build();
+ moduleService.loadModule(module1Descriptor);
+ moduleService.loadModule(module2Descriptor);
+
+ assertThatThrownBy(() -> {
+ this.getClass().getClassLoader().loadClass("org.apache.geode.Module1");
+ }).isInstanceOf(ClassNotFoundException.class);
+
+ assertThatThrownBy(() -> {
+ this.getClass().getClassLoader().loadClass("org.apache.geode.Module2");
+ }).isInstanceOf(ClassNotFoundException.class);
+ }
+
+ @Test
+ public void loadSingleModuleFromSingleJarNoDependencies() throws ClassNotFoundException {
+ ModuleDescriptor module1Descriptor = new ModuleDescriptor.Builder("module1", "1.0")
+ .fromSources(MODULE1_PATH)
+ .build();
+ assertThat(moduleService.loadModule(module1Descriptor)).isTrue();
+
+ moduleService.getModule(module1Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module1");
+ }
+
+ @Test
+ public void loadSingleModuleFromMultipleJarsNoDependencies() throws ClassNotFoundException {
+ ModuleDescriptor moduleDescriptor = new ModuleDescriptor.Builder("multiJarModule", "1.0")
+ .fromSources(MODULE1_PATH, MODULE2_PATH)
+ .build();
+ assertThat(moduleService.loadModule(moduleDescriptor)).isTrue();
+
+ moduleService.getModule(moduleDescriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module1");
+ moduleService.getModule(moduleDescriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module2");
+ }
+
+ @Test
+ public void loadMultipleModulesFromMultipleJarsNoDependencies() throws ClassNotFoundException {
+ ModuleDescriptor module1Descriptor = new ModuleDescriptor.Builder("module1", "1.0")
+ .fromSources(MODULE1_PATH, MODULE2_PATH)
+ .build();
+ ModuleDescriptor module2Descriptor = new ModuleDescriptor.Builder("module2", "1.0")
+ .fromSources(MODULE3_PATH, MODULE4_PATH)
+ .build();
+
+ assertThat(moduleService.loadModule(module1Descriptor)).isTrue();
+ assertThat(moduleService.loadModule(module2Descriptor)).isTrue();
+
+ moduleService.getModule(module1Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module1");
+ moduleService.getModule(module1Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module2");
+
+ moduleService.getModule(module2Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module3");
+ moduleService.getModule(module2Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module4");
+ }
+
+ @Test
+ public void modulesCannotAccessOtherModulesMultipleModulesFromMultipleJarsNoDependencies()
+ throws ClassNotFoundException {
+ ModuleDescriptor module1Descriptor = new ModuleDescriptor.Builder("module1", "1.0")
+ .fromSources(MODULE1_PATH, MODULE2_PATH)
+ .build();
+ ModuleDescriptor module2Descriptor = new ModuleDescriptor.Builder("module2", "1.0")
+ .fromSources(MODULE3_PATH, MODULE4_PATH)
+ .build();
+
+ moduleService.loadModule(module1Descriptor);
+ moduleService.loadModule(module2Descriptor);
+
+ assertThatThrownBy(() -> {
+ moduleService.getModule(module1Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module3");
+ }).isInstanceOf(ClassNotFoundException.class);
+ assertThatThrownBy(() -> {
+ moduleService.getModule(module1Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module4");
+ }).isInstanceOf(ClassNotFoundException.class);
+
+ assertThatThrownBy(() -> {
+ moduleService.getModule(module2Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module1");
+ }).isInstanceOf(ClassNotFoundException.class);
+ assertThatThrownBy(() -> {
+ moduleService.getModule(module2Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module2");
+ }).isInstanceOf(ClassNotFoundException.class);
+ }
+
+ @Test
+ public void loadMultipleModulesFromMultipleJarsWithDependencies() throws ClassNotFoundException {
+ ModuleDescriptor module1Descriptor = new ModuleDescriptor.Builder("module1", "1.0")
+ .fromSources(MODULE1_PATH, MODULE2_PATH)
+ .build();
+ ModuleDescriptor module2Descriptor = new ModuleDescriptor.Builder("module2", "1.0")
+ .fromSources(MODULE3_PATH, MODULE4_PATH)
+ .dependsOnModules(module1Descriptor.getVersionedName())
+ .build();
+
+ assertThat(moduleService.loadModule(module1Descriptor)).isTrue();
+ assertThat(moduleService.loadModule(module2Descriptor)).isTrue();
+
+ moduleService.getModule(module2Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module1");
+ moduleService.getModule(module2Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module2");
+ moduleService.getModule(module2Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module3");
+ moduleService.getModule(module2Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module4");
+ }
+
+ @Test
+ public void dependenciesDoNotGoBothWaysMultipleModulesFromMultipleJars()
+ throws ClassNotFoundException {
+ ModuleDescriptor module1Descriptor = new ModuleDescriptor.Builder("module1", "1.0")
+ .fromSources(MODULE1_PATH, MODULE2_PATH)
+ .build();
+ ModuleDescriptor module2Descriptor = new ModuleDescriptor.Builder("module2", "1.0")
+ .fromSources(MODULE3_PATH, MODULE4_PATH)
+ .dependsOnModules(module1Descriptor.getVersionedName())
+ .build();
+
+ moduleService.loadModule(module1Descriptor);
+ moduleService.loadModule(module2Descriptor);
+
+ assertThatThrownBy(() -> {
+ moduleService.getModule(module1Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module3");
+ }).isInstanceOf(ClassNotFoundException.class);
+ assertThatThrownBy(() -> {
+ moduleService.getModule(module1Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module4");
+ }).isInstanceOf(ClassNotFoundException.class);
+ }
+
+ @Test
+ public void loadMultipleModulesFromSingleJarNoDependencies() throws ClassNotFoundException {
+ ModuleDescriptor module1Descriptor = new ModuleDescriptor.Builder("module1", "1.0")
+ .fromSources(MODULE1_PATH)
+ .build();
+ ModuleDescriptor module2Descriptor = new ModuleDescriptor.Builder("module2", "1.0")
+ .fromSources(MODULE2_PATH)
+ .build();
+ assertThat(moduleService.loadModule(module1Descriptor)).isTrue();
+ assertThat(moduleService.loadModule(module2Descriptor)).isTrue();
+
+ moduleService.getModule(module1Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module1");
+ moduleService.getModule(module2Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module2");
+ }
+
+ @Test
+ public void modulesCannotAccessOtherModulesMultipleModulesFromSingleJarNoDependencies()
+ throws ClassNotFoundException {
+ ModuleDescriptor module1Descriptor = new ModuleDescriptor.Builder("module1", "1.0")
+ .fromSources(MODULE1_PATH)
+ .build();
+ ModuleDescriptor module2Descriptor = new ModuleDescriptor.Builder("module2", "1.0")
+ .fromSources(MODULE2_PATH)
+ .build();
+ moduleService.loadModule(module1Descriptor);
+ moduleService.loadModule(module2Descriptor);
+
+ assertThatThrownBy(() -> {
+ moduleService.getModule(module1Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module2");
+ }).isInstanceOf(ClassNotFoundException.class);
+
+ assertThatThrownBy(() -> {
+ moduleService.getModule(module2Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module1");
+ }).isInstanceOf(ClassNotFoundException.class);
+ }
+
+ @Test
+ public void loadMultipleModulesFromSingleJarWithDependencies() throws ClassNotFoundException {
+ ModuleDescriptor module1Descriptor = new ModuleDescriptor.Builder("module1", "1.0")
+ .fromSources(MODULE1_PATH)
+ .build();
+ ModuleDescriptor module2Descriptor = new ModuleDescriptor.Builder("module2", "1.0")
+ .fromSources(MODULE2_PATH)
+ .dependsOnModules(module1Descriptor.getVersionedName())
+ .build();
+ assertThat(moduleService.loadModule(module1Descriptor)).isTrue();
+ assertThat(moduleService.loadModule(module2Descriptor)).isTrue();
+
+ moduleService.getModule(module1Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module1");
+ moduleService.getModule(module2Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module2");
+ moduleService.getModule(module2Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module1");
+ }
+
+ @Test
+ public void dependenciesDoNotGoBothWaysMultipleModulesFromSingleJar()
+ throws ClassNotFoundException {
+ ModuleDescriptor module1Descriptor = new ModuleDescriptor.Builder("module1", "1.0")
+ .fromSources(MODULE1_PATH)
+ .build();
+ ModuleDescriptor module2Descriptor = new ModuleDescriptor.Builder("module2", "1.0")
+ .fromSources(MODULE2_PATH)
+ .dependsOnModules(module1Descriptor.getVersionedName())
+ .build();
+ moduleService.loadModule(module1Descriptor);
+ moduleService.loadModule(module2Descriptor);
+
+ assertThatThrownBy(() -> {
+ moduleService.getModule(module1Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module2");
+ }).isInstanceOf(ClassNotFoundException.class);
+ }
+
+ @Test
+ public void loadModuleMultipleTimes() throws ClassNotFoundException {
+ ModuleDescriptor module1Descriptor = new ModuleDescriptor.Builder("module1", "1.0")
+ .fromSources(MODULE1_PATH)
+ .build();
+ assertThat(moduleService.loadModule(module1Descriptor)).isTrue();
+ assertThat(moduleService.loadModule(module1Descriptor)).isFalse();
+
+ moduleService.getModule(module1Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module1");
+ }
+
+ @Test
+ public void loadModulesWithSameNameAndDifferentVersions() throws ClassNotFoundException {
+ ModuleDescriptor module1Descriptor = new ModuleDescriptor.Builder("module1", "1.0")
+ .fromSources(MODULE1_PATH)
+ .build();
+ moduleService.loadModule(module1Descriptor);
+ ModuleDescriptor module2Descriptor = new ModuleDescriptor.Builder("module1", "2.0")
+ .fromSources(MODULE2_PATH)
+ .build();
+ moduleService.loadModule(module2Descriptor);
+
+ moduleService.getModule(module1Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module1");
+ assertThatThrownBy(() -> {
+ moduleService.getModule(module1Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module2");
+ }).isInstanceOf(ClassNotFoundException.class);
+
+ moduleService.getModule(module2Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module2");
+ assertThatThrownBy(() -> {
+ moduleService.getModule(module2Descriptor.getVersionedName()).getClassLoader()
+ .loadClass("org.apache.geode.Module1");
+ }).isInstanceOf(ClassNotFoundException.class);
+ }
+
+ @Test
+ public void loadModuleFromInvalidSource() {
+ ModuleDescriptor module1Descriptor = new ModuleDescriptor.Builder("module1", "1.0")
+ .fromSources("/there/is/nothing/here.jar")
+ .build();
+ assertThat(moduleService.loadModule(module1Descriptor)).isFalse();
+ assertThat(moduleService.getModule(module1Descriptor.getVersionedName())).isNull();
+ }
+
+ @Test
+ public void loadModuleFromMixOfValidAndInvalidSources() {
+ ModuleDescriptor module1Descriptor = new ModuleDescriptor.Builder("module1", "1.0")
+ .fromSources("/there/is/nothing/here.jar", MODULE1_PATH)
+ .build();
+ assertThat(moduleService.loadModule(module1Descriptor)).isFalse();
+ assertThat(moduleService.getModule(module1Descriptor.getVersionedName())).isNull();
+ }
+
+ @Test
+ public void loadModuleWithInvalidDependencies() {
+ ModuleDescriptor module1Descriptor = new ModuleDescriptor.Builder("module1", "1.0")
+ .fromSources(MODULE1_PATH)
+ .dependsOnModules("this_is_invalid")
+ .build();
+ assertThat(moduleService.loadModule(module1Descriptor)).isFalse();
+ assertThat(moduleService.getModule(module1Descriptor.getVersionedName())).isNull();
+ }
+
+ @Test
+ public void loadModuleWithMixOfValidAndInvalidDependencies() {
+ ModuleDescriptor module1Descriptor = new ModuleDescriptor.Builder("module1", "1.0")
+ .fromSources(MODULE1_PATH)
+ .build();
+ ModuleDescriptor module2Descriptor = new ModuleDescriptor.Builder("module2", "1.0")
+ .fromSources(MODULE2_PATH)
+ .dependsOnModules("this_is_invalid", module1Descriptor.getVersionedName())
+ .build();
+ moduleService.loadModule(module1Descriptor);
+ assertThat(moduleService.loadModule(module2Descriptor)).isFalse();
+ assertThat(moduleService.getModule(module2Descriptor.getVersionedName())).isNull();
+ }
+
+ @Test
+ public void getModuleNoModulesLoaded() {
+ assertThat(moduleService.getModule("module1:1.0")).isNull();
+ }
+
+ @Test
+ public void getModuleWithSingeModuleLoaded() {
+ ModuleDescriptor module1Descriptor = new ModuleDescriptor.Builder("module1", "1.0")
+ .fromSources(MODULE1_PATH)
+ .build();
+ moduleService.loadModule(module1Descriptor);
+ Module module = moduleService.getModule(module1Descriptor.getVersionedName());
+ assertThat(module).isNotNull();
+ assertThat(module.getName()).isEqualTo(module1Descriptor.getVersionedName());
+ }
+
+ @Test
+ public void getModuleWithMultipleModulesLoaded() {
+ ModuleDescriptor module1Descriptor = new ModuleDescriptor.Builder("module1", "1.0")
+ .fromSources(MODULE1_PATH)
+ .build();
+ moduleService.loadModule(module1Descriptor);
+ ModuleDescriptor module2Descriptor = new ModuleDescriptor.Builder("module2", "1.0")
+ .fromSources(MODULE2_PATH)
+ .build();
+ moduleService.loadModule(module2Descriptor);
+
+ Module module1 = moduleService.getModule(module1Descriptor.getVersionedName());
+ assertThat(module1).isNotNull();
+ assertThat(module1.getName()).isEqualTo(module1Descriptor.getVersionedName());
+
+ Module module2 = moduleService.getModule(module2Descriptor.getVersionedName());
+ assertThat(module2).isNotNull();
+ assertThat(module2.getName()).isEqualTo(module2Descriptor.getVersionedName());
+ }
+}
diff --git a/geode-modules/src/test/resources/expected-pom.xml b/geode-modules/src/test/resources/expected-pom.xml
new file mode 100644
index 0000000..50c2beb
--- /dev/null
+++ b/geode-modules/src/test/resources/expected-pom.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+ <!--
+ 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.
+ -->
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-modules</artifactId>
+ <version>1.13.0-SNAPSHOT</version>
+ <name>Apache Geode</name>
+ <description>Apache Geode provides a database-like consistency model, reliable transaction processing and a shared-nothing architecture to maintain very low latency performance with high concurrency processing</description>
+ <url>http://geode.apache.org</url>
+ <licenses>
+ <license>
+ <name>The Apache Software License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+ </license>
+ </licenses>
+ <scm>
+ <connection>scm:git:https://github.com:apache/geode.git</connection>
+ <developerConnection>scm:git:https://github.com:apache/geode.git</developerConnection>
+ <url>https://github.com/apache/geode</url>
+ </scm>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-all-bom</artifactId>
+ <version>1.13.0-SNAPSHOT</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-common</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-common-services</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.modules</groupId>
+ <artifactId>jboss-modules</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-logging</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-log4j</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-core</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/geode-modules/src/testModules/module1/java/org/apache/geode/Module1.java b/geode-modules/src/testModules/module1/java/org/apache/geode/Module1.java
new file mode 100644
index 0000000..684a71c
--- /dev/null
+++ b/geode-modules/src/testModules/module1/java/org/apache/geode/Module1.java
@@ -0,0 +1,19 @@
+/*
+ * 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.geode;
+
+public class Module1 {
+}
diff --git a/geode-modules/src/testModules/module2/java/org.apache.geode/Module2.java b/geode-modules/src/testModules/module2/java/org.apache.geode/Module2.java
new file mode 100644
index 0000000..9cbac0f
--- /dev/null
+++ b/geode-modules/src/testModules/module2/java/org.apache.geode/Module2.java
@@ -0,0 +1,19 @@
+/*
+ * 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.geode;
+
+public class Module2 {
+}
diff --git a/geode-modules/src/testModules/module3/java/org/apache/geode/Module3.java b/geode-modules/src/testModules/module3/java/org/apache/geode/Module3.java
new file mode 100644
index 0000000..87035eb
--- /dev/null
+++ b/geode-modules/src/testModules/module3/java/org/apache/geode/Module3.java
@@ -0,0 +1,19 @@
+/*
+ * 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.geode;
+
+public class Module3 {
+}
diff --git a/geode-modules/src/testModules/module4/java/org/apache/geode/Module4.java b/geode-modules/src/testModules/module4/java/org/apache/geode/Module4.java
new file mode 100644
index 0000000..c494905
--- /dev/null
+++ b/geode-modules/src/testModules/module4/java/org/apache/geode/Module4.java
@@ -0,0 +1,19 @@
+/*
+ * 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.geode;
+
+public class Module4 {
+}
diff --git a/settings.gradle b/settings.gradle
index 501a179..cefea67 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -68,6 +68,8 @@ include 'geode-concurrency-test'
include 'boms:geode-client-bom'
include 'boms:geode-all-bom'
include 'static-analysis:pmd-rules'
+include 'geode-common-services'
+include 'geode-modules'
['1.0.0-incubating',