You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by ng...@apache.org on 2010/05/24 22:25:46 UTC

svn commit: r947790 - in /mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/vysper/ src/main/java/org/apache/vysper/xmpp/ src/main/java/org/a...

Author: ngn
Date: Mon May 24 20:25:45 2010
New Revision: 947790

URL: http://svn.apache.org/viewvc?rev=947790&view=rev
Log:
Adding module for BOSH

Added:
    mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/
    mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/pom.xml
    mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/
    mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/
    mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/
    mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/
    mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/
    mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/
    mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/
    mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/
    mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/
    mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContext.java
    mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshEndpoint.java
    mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshIoHandler.java
    mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/ServerMain.java

Added: mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/pom.xml
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/pom.xml?rev=947790&view=auto
==============================================================================
--- mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/pom.xml (added)
+++ mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/pom.xml Mon May 24 20:25:45 2010
@@ -0,0 +1,70 @@
+<?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/maven-v4_0_0.xsd">
+  <parent>
+    <artifactId>vysper-extensions</artifactId>
+    <groupId>org.apache.vysper</groupId>
+    <version>0.6-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.vysper.extensions</groupId>
+  <artifactId>xep0124-xep0206-bosh</artifactId>
+  <name>Apache Vysper XEP-0124 and XEP-0206 BOSH</name>
+  <version>0.6-SNAPSHOT</version>
+  
+  
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.vysper</groupId>
+      <artifactId>spec-compliance</artifactId>
+      <optional>true</optional>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.apache.vysper</groupId>
+      <artifactId>vysper-core</artifactId>
+    </dependency>
+    
+	<dependency>
+	  <groupId>org.eclipse.jetty</groupId>
+	  <artifactId>jetty-server</artifactId>
+	  <version>7.1.1.v20100517</version>
+	</dependency>
+
+    <!-- Runtime dependencies -->
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    
+    <dependency>
+      <groupId>log4j</groupId>
+      <artifactId>log4j</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+      
+    <!-- Test dependencies -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>

Added: mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContext.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContext.java?rev=947790&view=auto
==============================================================================
--- mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContext.java (added)
+++ mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContext.java Mon May 24 20:25:45 2010
@@ -0,0 +1,89 @@
+/*
+ *  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.vysper.xmpp.extension.xep0124;
+
+import org.apache.mina.core.future.CloseFuture;
+import org.apache.mina.core.future.IoFuture;
+import org.apache.mina.core.future.IoFutureListener;
+import org.apache.mina.core.session.IoSession;
+import org.apache.vysper.mina.codec.StanzaWriteInfo;
+import org.apache.vysper.xmpp.protocol.SessionStateHolder;
+import org.apache.vysper.xmpp.server.AbstractSessionContext;
+import org.apache.vysper.xmpp.server.ServerRuntimeContext;
+import org.apache.vysper.xmpp.server.SessionState;
+import org.apache.vysper.xmpp.stanza.Stanza;
+import org.apache.vysper.xmpp.writer.StanzaWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * connects MINA 2 frontend to the vysper backend through the Bosh protocol
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class BoshBackedSessionContext extends AbstractSessionContext implements StanzaWriter, IoFutureListener {
+
+    final Logger logger = LoggerFactory.getLogger(BoshBackedSessionContext.class);
+
+    private IoSession minaSession;
+    private boolean openingStanzaWritten = false;
+    protected CloseFuture closeFuture;
+
+    public BoshBackedSessionContext(
+            ServerRuntimeContext serverRuntimeContext,
+            SessionStateHolder sessionStateHolder,
+            IoSession minaSession) {
+        super(serverRuntimeContext, sessionStateHolder);
+        this.minaSession = minaSession;
+        closeFuture = minaSession.getCloseFuture();
+        closeFuture.addListener(this);
+        sessionStateHolder.setState(SessionState.INITIATED); // connection established
+    }
+
+    public StanzaWriter getResponseWriter() {
+        return this;
+    }
+
+    public void setIsReopeningXMLStream() {
+        openingStanzaWritten = false;
+    }
+
+    public void write(Stanza stanza) {
+        minaSession.write(new StanzaWriteInfo(stanza, !openingStanzaWritten));
+        openingStanzaWritten = true;
+    }
+
+    public void close() {
+        logger.info("session will be closed now");
+        closeFuture.setClosed();
+        minaSession.close(true);
+    }
+
+    public void operationComplete(IoFuture ioFuture) {
+        // close future notification
+        logger.info("close future called");
+    }
+
+	public void switchToTLS() {
+		// Bosh cannot switch dynamically
+		// SSL can be enabled/disabled in BoshEndpoint#setSslEnabled()
+	}
+}

Added: mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshEndpoint.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshEndpoint.java?rev=947790&view=auto
==============================================================================
--- mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshEndpoint.java (added)
+++ mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshEndpoint.java Mon May 24 20:25:45 2010
@@ -0,0 +1,77 @@
+/*
+ *  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.vysper.xmpp.extension.xep0124;
+
+import java.io.IOException;
+
+import org.apache.vysper.xmpp.server.Endpoint;
+import org.apache.vysper.xmpp.server.ServerRuntimeContext;
+import org.eclipse.jetty.server.Server;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Allows HTTP clients to communicate through the Bosh protocol (http://xmpp.org/extensions/xep-0124.html)
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class BoshEndpoint implements Endpoint {
+	
+	private final Logger logger = LoggerFactory.getLogger(BoshEndpoint.class);
+
+    private ServerRuntimeContext serverRuntimeContext;
+
+    private int port = 8080;
+
+    private Server server;
+    
+    public void setServerRuntimeContext(ServerRuntimeContext serverRuntimeContext) {
+        this.serverRuntimeContext = serverRuntimeContext;
+    }
+
+    public void setPort(int port) {
+        this.port = port;
+    }
+    
+    public void setSslEnabled(boolean value) {
+    	// TODO:
+    }
+    
+    public void start() throws IOException {
+    	server = new Server(port);
+    	BoshIoHandler boshIoHandler = new BoshIoHandler();
+    	boshIoHandler.setServerRuntimeContext(serverRuntimeContext);
+    	server.setHandler(boshIoHandler); 
+    	try {
+			server.start();
+		} catch (Exception e) {
+			throw new IOException(e);
+		}
+    }
+
+    public void stop() {
+    	try {
+			server.stop();
+		} catch (Exception e) {
+			logger.warn("Could not stop the Jetty server", e);
+		}
+    }
+
+}

Added: mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshIoHandler.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshIoHandler.java?rev=947790&view=auto
==============================================================================
--- mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshIoHandler.java (added)
+++ mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshIoHandler.java Mon May 24 20:25:45 2010
@@ -0,0 +1,110 @@
+/*
+ *  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.vysper.xmpp.extension.xep0124;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.Random;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.vysper.xmpp.server.ServerRuntimeContext;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Handles Bosh stanzas
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class BoshIoHandler extends AbstractHandler {
+
+    final Logger logger = LoggerFactory.getLogger(BoshIoHandler.class);
+
+    private ServerRuntimeContext serverRuntimeContext;
+
+    public void setServerRuntimeContext(ServerRuntimeContext serverRuntimeContext) {
+        this.serverRuntimeContext = serverRuntimeContext;
+    }
+    
+    public void handle(String target, Request baseRequest, 
+			HttpServletRequest request, HttpServletResponse response)
+			throws IOException, ServletException {
+    	
+    	if (request.getMethod().equals("GET") && request.getPathInfo().equals("/crossdomain.xml")) {
+    		// request for the cross-domain policy from Flash (e.g. flXHR)
+    		response.setContentType("text/xml");
+    		response.setStatus(HttpServletResponse.SC_OK);
+    		response.getWriter().println("<cross-domain-policy><site-control permitted-cross-domain-policies='all'/><allow-access-from domain='*'/><allow-http-request-headers-from domain='*' headers='*'/></cross-domain-policy>");
+    		((Request)request).setHandled(true);
+    		return;
+    	}
+    	
+    	if (!request.getMethod().equals("POST")) {
+    		// it should not reach here normally, but it can happen if the user explicitly makes a non-POST request (e.g. GET, DELETE, etc)
+    		response.setContentType("text/html");
+    		response.setStatus(HttpServletResponse.SC_OK);
+    		response.getWriter().println("<html>This is an XMPP BOSH connection manager, you need to use a compatible BOSH client to use its services!</html>");
+    		((Request)request).setHandled(true);
+    		return;
+    	}
+    	
+    	BufferedReader reader = request.getReader();
+    	
+    	char [] buf = new char[1024];
+    	StringBuilder sb = new StringBuilder();
+    	
+    	for (;;) {
+    		int n = reader.read(buf);
+    		if (n == -1) {
+    			break;
+    		}
+    		sb.append(buf, 0, n);
+    	}
+    	
+    	String body = sb.toString();
+    	logger.debug("BOSH CM received : {}", body);
+    	
+    	
+    	// test if this is the first request (kind of a hack - should be parsing XML)
+    	if (body.indexOf("sid=") == -1) {
+    		// initial request
+    		String sid = Long.toString(new Random().nextLong(), 16);
+    		response.setContentType("text/xml; charset=utf-8");
+    		response.setStatus(HttpServletResponse.SC_OK);
+    		response.getWriter().print("<body xmlns='http://jabber.org/protocol/httpbind' wait='60' inactivity='60' polling='5' requests='2' hold='1' maxpause='120' sid='");
+    		response.getWriter().print(sid);
+    		response.getWriter().print("' ver='1.6' from='vysper.org'/>");
+    		((Request)request).setHandled(true);
+    		return;
+    	}
+    	
+    	// session exists
+    	// not handled yet, TODO
+    	response.setContentType("text/xml; charset=utf-8");
+		response.setStatus(HttpServletResponse.SC_OK);
+    	((Request)request).setHandled(true);
+    }
+
+}

Added: mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/ServerMain.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/ServerMain.java?rev=947790&view=auto
==============================================================================
--- mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/ServerMain.java (added)
+++ mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/ServerMain.java Mon May 24 20:25:45 2010
@@ -0,0 +1,136 @@
+package org.apache.vysper.xmpp.extension.xep0124;
+/*
+ *  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.
+ *
+ */
+
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.vysper.mina.TCPEndpoint;
+import org.apache.vysper.storage.StorageProviderRegistry;
+import org.apache.vysper.storage.inmemory.MemoryStorageProviderRegistry;
+import org.apache.vysper.xmpp.addressing.EntityFormatException;
+import org.apache.vysper.xmpp.addressing.EntityImpl;
+import org.apache.vysper.xmpp.authorization.AccountCreationException;
+import org.apache.vysper.xmpp.authorization.AccountManagement;
+import org.apache.vysper.xmpp.modules.Module;
+import org.apache.vysper.xmpp.modules.extension.xep0049_privatedata.PrivateDataModule;
+import org.apache.vysper.xmpp.modules.extension.xep0054_vcardtemp.VcardTempModule;
+import org.apache.vysper.xmpp.modules.extension.xep0092_software_version.SoftwareVersionModule;
+import org.apache.vysper.xmpp.modules.extension.xep0119_xmppping.XmppPingModule;
+import org.apache.vysper.xmpp.modules.extension.xep0202_entity_time.EntityTimeModule;
+import org.apache.vysper.xmpp.server.XMPPServer;
+
+/**
+ * starts the server as a standalone application
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class ServerMain {
+
+    /**
+     * boots the server as a standalone application
+     * 
+     * adding a module from the command line:
+     * using a runtime property, one or more modules can be specified, like this:
+     * -Dvysper.add.module=org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.PublishSubscribeModule,... more ...
+     * 
+     * @param args
+     */
+    public static void main(String[] args) throws AccountCreationException, EntityFormatException {
+
+        String addedModuleProperty = System.getProperty("vysper.add.module");
+        List<Module> listOfModules = null;
+        if (addedModuleProperty != null) {
+            String[] moduleClassNames = addedModuleProperty.split(",");
+            listOfModules = createModuleInstances(moduleClassNames);
+        }
+
+        // choose the storage you want to use
+        //StorageProviderRegistry providerRegistry = new JcrStorageProviderRegistry();
+        StorageProviderRegistry providerRegistry = new MemoryStorageProviderRegistry();
+
+        final AccountManagement accountManagement = (AccountManagement)providerRegistry.retrieve(AccountManagement.class);
+
+        if (!accountManagement.verifyAccountExists(EntityImpl.parse("user1@vysper.org"))) {
+            accountManagement.addUser("user1@vysper.org", "password1");
+        }
+        if (!accountManagement.verifyAccountExists(EntityImpl.parse("user2@vysper.org"))) {
+            accountManagement.addUser("user2@vysper.org", "password1");
+        }
+        if (!accountManagement.verifyAccountExists(EntityImpl.parse("user3@vysper.org"))) {
+            accountManagement.addUser("user3@vysper.org", "password1");
+        }
+
+        XMPPServer server = new XMPPServer("vysper.org");
+        server.addEndpoint(new TCPEndpoint());
+        BoshEndpoint boshEndpoint = new BoshEndpoint();
+        server.addEndpoint(boshEndpoint);
+        //server.addEndpoint(new StanzaSessionFactory());
+        server.setStorageProviderRegistry(providerRegistry);
+
+        server.setTLSCertificateInfo(new File("src/main/config/bogus_mina_tls.cert"), "boguspw");
+
+        try {
+            server.start();
+            System.out.println("vysper server is running...");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        server.addModule(new SoftwareVersionModule());
+        server.addModule(new EntityTimeModule());
+        server.addModule(new VcardTempModule());
+        server.addModule(new XmppPingModule());
+        server.addModule(new PrivateDataModule());
+
+        if (listOfModules != null) {
+            for (Module module : listOfModules) {
+                server.addModule(module);
+            }
+        }
+    }
+
+    private static List<Module> createModuleInstances(String[] moduleClassNames) {
+        List<Module> modules = new ArrayList<Module>();
+        
+        for (String moduleClassName : moduleClassNames) {
+            Class<Module> moduleClass;
+            try {
+                moduleClass = (Class<Module>)Class.forName(moduleClassName);
+            } catch (ClassCastException e) {
+                System.err.println("not a Vysper module class: " + moduleClassName);
+                continue;
+            } catch (ClassNotFoundException e) {
+                System.err.println("could not load module class " + moduleClassName);
+                continue;
+            }
+            try {
+                Module module = moduleClass.newInstance();
+                modules.add(module);
+            } catch (Exception e) {
+                System.err.println("failed to instantiate module class " + moduleClassName);
+                continue;
+            }
+        }
+        return modules;
+    }
+}