Commits

Stephen McKamey committed 4ba0ef1

adding helper classes for wiring up view stack

Comments (0)

Files changed (7)

duel/duel-compiler/pom.xml

 	<parent>
 		<groupId>org.duelengine.duel</groupId>
 		<artifactId>duel</artifactId>
-		<version>0.4.0</version>
+		<version>0.4.1</version>
 	</parent>
 
 	<artifactId>duel-compiler</artifactId>

duel/duel-js/pom.xml

 	<parent>
 		<groupId>org.duelengine.duel</groupId>
 		<artifactId>duel</artifactId>
-		<version>0.4.0</version>
+		<version>0.4.1</version>
 	</parent>
 
 	<artifactId>duel-js</artifactId>

duel/duel-maven-plugin/pom.xml

 	<parent>
 		<groupId>org.duelengine.duel</groupId>
 		<artifactId>duel</artifactId>
-		<version>0.4.0</version>
+		<version>0.4.1</version>
 	</parent>
 
 	<artifactId>duel-maven-plugin</artifactId>

duel/duel-runtime/pom.xml

 	<parent>
 		<groupId>org.duelengine.duel</groupId>
 		<artifactId>duel</artifactId>
-		<version>0.4.0</version>
+		<version>0.4.1</version>
 	</parent>
 
 	<artifactId>duel-runtime</artifactId>
 	</properties>
 
 	<dependencies>
+		<!-- JAX-RS interfaces -->
 		<dependency>
 			<groupId>javax.ws.rs</groupId>
 			<artifactId>jsr311-api</artifactId>
 			<version>1.0</version>
 			<scope>provided</scope>
 		</dependency>
+		<!-- Servlet interfaces -->
+		<dependency>
+			<groupId>javax.servlet</groupId>
+			<artifactId>servlet-api</artifactId>
+			<version>2.5</version>
+			<scope>provided</scope>
+		</dependency>
 		<dependency>
 			<groupId>junit</groupId>
 			<artifactId>junit</artifactId>

duel/duel-runtime/src/main/java/org/duelengine/duel/util/ClassEnumerator.java

+package org.duelengine.duel.util;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.jar.*;
+
+/**
+ * Utility for enumerating available classes in a particular package
+ */
+public final class ClassEnumerator {
+
+	private static final String CLASS_FILE = ".class";
+	private static final String JAR_FILE = ".jar";
+
+	/**
+	 * Loads classes in the specified package from the current thread ClassLoader
+	 * @param packageName
+	 * @return
+	 * @throws IOException
+	 * @throws ClassNotFoundException
+	 */
+	public static Set<Class<?>> getClasses(String packageName)
+			throws IOException, ClassNotFoundException {
+
+		return getClasses(packageName, Thread.currentThread().getContextClassLoader());
+	}
+
+	/**
+	 * Loads classes in the specified package from the specified ClassLoader
+	 * @param packageName
+	 * @param loader
+	 * @return
+	 * @throws IOException
+	 * @throws ClassNotFoundException
+	 */
+	public static Set<Class<?>> getClasses(String packageName, ClassLoader loader)
+			throws IOException, ClassNotFoundException {
+
+		String path = packageName.replace('.', '/');
+		Enumeration<URL> resources = loader.getResources(path);
+		if (resources == null) {
+			return Collections.emptySet();
+		}
+
+		Set<Class<?>> classes = new HashSet<Class<?>>();
+		while (resources.hasMoreElements()) {
+			String filePath = resources.nextElement().getPath();
+			if (filePath == null) {
+				continue;
+			}
+
+			// decode URL encoded characters
+			filePath = URLDecoder.decode(filePath, "UTF-8");
+
+			int bang = filePath.indexOf('!');
+			if ((bang > 0) & (filePath.lastIndexOf(JAR_FILE) > 0)) {
+				String jarPath = filePath.substring(0, bang).substring(filePath.lastIndexOf(':')+1);
+				classes.addAll(getFromJAR(path, jarPath));
+
+			} else {
+				classes.addAll(getFromDirectory(packageName, new File(filePath)));
+			}
+		}
+
+		return classes;
+	}
+
+	/**
+	 * Loads classes in the specified package from the specified directory
+	 * @param packageName
+	 * @param directory
+	 * @return
+	 * @throws ClassNotFoundException
+	 */
+	public static Set<Class<?>> getFromDirectory(String packageName, File directory)
+			throws ClassNotFoundException {
+
+		Set<Class<?>> classes = new HashSet<Class<?>>();
+		if (directory.exists()) {
+			for (String file : directory.list()) {
+				if (file.endsWith(CLASS_FILE)) {
+					String name = packageName + '.' + file.substring(0, file.lastIndexOf('.'));;
+					classes.add(Class.forName(name));
+				}
+			}
+		}
+		return classes;
+	}
+
+	/**
+	 * Loads classes in the specified package from the specified JAR
+	 * @param packageName
+	 * @param jar
+	 * @return
+	 * @throws FileNotFoundException
+	 * @throws IOException
+	 * @throws ClassNotFoundException
+	 */
+	public static Set<Class<?>> getFromJAR(String packageName, String jar)
+			throws FileNotFoundException, IOException, ClassNotFoundException {
+
+		JarInputStream jarFile = new JarInputStream(new FileInputStream(jar));
+		Set<Class<?>> classes = new HashSet<Class<?>>();
+
+		JarEntry jarEntry;
+		while ((jarEntry = jarFile.getNextJarEntry()) != null) {
+			String className = jarEntry.getName();
+			if (className.endsWith(CLASS_FILE)) {
+				className = className.substring(0, className.lastIndexOf('.'));
+				if (className.startsWith(packageName)) {
+					classes.add(Class.forName(className.replace('/', '.')));
+				}
+			}
+		}
+
+		return classes;
+	}
+}

duel/duel-runtime/src/main/java/org/duelengine/duel/util/DefaultWrapperServlet.java

+package org.duelengine.duel.util;
+
+import java.io.IOException;
+import javax.servlet.*;
+import javax.servlet.http.*;
+
+/**
+ * Simple wrapper for passing the request onto the default servlet
+ */
+public class DefaultWrapperServlet extends HttpServlet {
+
+	private static final long serialVersionUID = -351152009226372681L;
+
+	public void doGet(HttpServletRequest request, HttpServletResponse response)
+		throws ServletException, IOException {
+
+		getServletContext().getNamedDispatcher("default").forward(
+			new HttpServletRequestWrapper(request) {
+				public String getServletPath() { return ""; }
+			},
+			response);
+	}
+}
 	
 	<groupId>org.duelengine.duel</groupId>
 	<artifactId>duel</artifactId>
-	<version>0.4.0</version>
+	<version>0.4.1</version>
 	<packaging>pom</packaging>
 
 	<name>DUEL</name>