Title: [773] trunk/rails-integration/src/main/java/org/jruby/webapp: Don' t save a dispatcher, and also implement UGLY workaround for Oracle
Revision
773
Author
olabini
Date
2007-10-17 11:20:11 -0400 (Wed, 17 Oct 2007)

Log Message

Don't save a dispatcher, and also implement UGLY workaround for Oracle

Modified Paths

Diff

Modified: trunk/rails-integration/src/main/java/org/jruby/webapp/FileServlet.java (772 => 773)


--- trunk/rails-integration/src/main/java/org/jruby/webapp/FileServlet.java	2007-10-16 12:32:16 UTC (rev 772)
+++ trunk/rails-integration/src/main/java/org/jruby/webapp/FileServlet.java	2007-10-17 15:20:11 UTC (rev 773)
@@ -1,321 +1,322 @@
-package org.jruby.webapp;
-
-import org.jruby.webapp.util.FileUtil;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.File;
-import java.io.IOException;
-import java.io.FileNotFoundException;
-import java.io.OutputStream;
-import java.io.FileInputStream;
-import java.util.Calendar;
-import java.util.Date;
-import java.text.SimpleDateFormat;
-import java.nio.channels.FileChannel;
-import java.nio.ByteBuffer;
-
-/**
- * This servlet returns a static file.
- *
- * @author Robert Egglestone
- */
-public class FileServlet extends HttpServlet {
-
-    private static final String METHOD_DELETE = "DELETE";
-    private static final String METHOD_HEAD = "HEAD";
-    private static final String METHOD_GET = "GET";
-    private static final String METHOD_OPTIONS = "OPTIONS";
-    private static final String METHOD_POST = "POST";
-    private static final String METHOD_PUT = "PUT";
-    private static final String METHOD_TRACE = "TRACE";
-
-	public static final String FALLBACK_SERVLET_PROPERTY = "files.default";
-
-	private static final String[] DEFAULT_WELCOME_FILES = {"index.html", "index.htm"};
-
-	public final static String CACHE_CONTROL_HEADER = "Cache-Control";
-	public final static String EXPIRES_HEADER = "Expires";
-	public final static String DATE_HEADER = "Date";
-
-	private int bufferSize = 1024;
-
-	private File root;
-
-	private String prefix;
-
-	private boolean setCacheHeaders;
-	private int maxAge;
-
-	/**
-	 * A servlet to pass control to if the file does not exist.
-	 */
-	private RequestDispatcher defaultServletDispatcher;
-
-	/**
-	 * Initialize the servlet, and determine the webapp root.
-	 */
-	public void init() throws ServletException {
-		prefix = findPrefix();
-		root = findRoot();
-
-		// determine the cache values
-		setCacheHeaders = getServletConfig().getInitParameter("maxAge") != null;
-		if (setCacheHeaders) {
-			maxAge = Integer.parseInt(getServletConfig().getInitParameter("maxAge"));
-		}
-
-		// check for default fallback servlet
-		ServletContext context = getServletContext();
-		String defaultServletName = getServletConfig().getInitParameter("defaultServlet");
-		if (defaultServletName == null) {
-			defaultServletName = context.getInitParameter(FileServlet.FALLBACK_SERVLET_PROPERTY);
-		}
-		if (defaultServletName != null && defaultServletName.length() != 0) {
-			defaultServletDispatcher = context.getNamedDispatcher(defaultServletName);
-		}
-	}
-
-	/**
-	 * A prefix to prepend on the path when translating from URL to file location, typically "/public".
-	 */
-	protected String findPrefix() {
-		String prefix = getServletContext().getInitParameter("files.prefix");
-		if (prefix == null) prefix = "/public";
-		// prefix must start with a slash if it's specified
-		if (prefix.length() > 0 && !prefix.startsWith("/")) {
-			prefix = "/" + prefix;
-		}
-		return prefix;
-	}
-
-	/**
-	 * Root of the webapp, may be null in which case it is determined from the servlet api.
-	 * The root should be an absolute path that refers to a directory.
-	 */
-	protected File findRoot() throws ServletException {
-		String rootPath = getServletContext().getInitParameter("files.root");
-		if (rootPath == null) {
-			rootPath = FileUtil.getPath(getServletContext(), "/");
-		}
-
-		File root = new File(rootPath);
-		if (!root.isDirectory()) {
-			throw new ServletException("Webapp root does not point to a directory");
-		}
-
-		return root;
-	}
-
-	public String[] getWelcomeFiles() {
-		String[] welcomeFiles;
-
-		String welcomeFilesString = getServletContext().getInitParameter("files.welcome");
-		if (welcomeFilesString != null) {
-			welcomeFiles = parseCommaList(welcomeFilesString);
-		} else {
-			welcomeFiles = DEFAULT_WELCOME_FILES;
-		}
-
-		return welcomeFiles;
-	}
-
-	private String[] parseCommaList(String commaList) {
-		String[] parts = commaList.split(",");
-		for(int i=0; i<parts.length; i++) {
-			parts[i] = parts[i].trim();
-		}
-		return parts;
-	}
-
-	/**
-	 * Look for a file matching the request.
-	 */
-	protected File getFile(HttpServletRequest request) {
-		// find the location of the file
-		String contextPath = request.getContextPath();
-		String relativePath = request.getRequestURI().substring(contextPath.length());
-
-		// normalize the path
-		relativePath = relativePath.replaceAll("\\\\", "/").replaceAll("//", "/");
-
-		// determine the file path to check for
-		String filePath;
-		if (root == null) {
-			filePath = prefix + relativePath;
-		} else {
-			filePath = root.getAbsolutePath() + prefix + relativePath;
-		}
-
-		return getFile(filePath);
-	}
-
-	/**
-	 * Look for a file matching the specified path.
-	 * This should also check default extensions, and for index files in the case of a directory.
-	 */
-	protected File getFile(String filePath) {
-		// try the exact match
-		File fileLocation = getExactFile(filePath);
-		if (fileLocation != null) return fileLocation;
-
-		// try default extension
-		fileLocation = getExactFile(filePath + ".html");
-		if (fileLocation != null) return fileLocation;
-
-		// try welcome files
-		String[] welcomeFiles = getWelcomeFiles();
-		for (int i = 0; i < welcomeFiles.length; i++) {
-
-			fileLocation = getExactFile(filePath + "/" + welcomeFiles[i]);
-			if (fileLocation != null) return fileLocation;
-		}
-
-		// no match was found
-		return null;
-	}
-
-	/**
-	 * Look for a file with this exact path.
-	 */
-	protected File getExactFile(String path) {
-		// try to load the resource
-		File filePath = new File(path);
-		if (!filePath.isFile()) return null;
-		return filePath;
-	}
-
-	private String formatDateForHeader(Date date) {
-	  String safari3OnlyAccessThisStyleDataFormat = "EEE, d MMM yyyy HH:mm:ss z";
-	  return new SimpleDateFormat(safari3OnlyAccessThisStyleDataFormat).format(date);
-	}
-
-	/**
-	 * Transfer the file.
-	 */
-	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
-		try {
-			// check the file and open it
-			File fileLocation = getFile(request);
-			if (fileLocation != null) {
-				// file was found, all good
-			} else if (defaultServletDispatcher != null) {
-				// forward request to the default servlet
-				defaultServletDispatcher.forward(request, response);
-				return;
-			} else {
-				// file not found
-				log("File not found: " + request.getRequestURI());
-				throw new FileNotFoundException(request.getRequestURI());
-			}
-
-			// check for modifications
-			long ifModifiedSince = request.getDateHeader("If-Modified-Since");
-			if (ifModifiedSince != -1) {
-				long lastModified = fileLocation.lastModified();
-				if (lastModified == 0) {
-					// last modified date is not known
-				} else if (lastModified < ifModifiedSince) {
-					throw new NotModifiedException();
-				} else {
-					response.setDateHeader("Last-Modified", lastModified);
-				}
-			}
-
-			// set cache headers
-			if (setCacheHeaders) {
-				response.setHeader(CACHE_CONTROL_HEADER, "max-age=" + maxAge);
-				Calendar now = Calendar.getInstance();
-				response.setHeader(DATE_HEADER, formatDateForHeader(now.getTime()));
-				now.add(Calendar.SECOND, maxAge);
-				response.setHeader(EXPIRES_HEADER, formatDateForHeader(now.getTime()));
-			}
-
-			// set the content type
-			String contentType = guessContentTypeFromName(fileLocation.getName());
-			response.setContentType(contentType);
-
-			if (request.getMethod().equals(METHOD_HEAD)) {
-				// head requests don't send the body
-			} else if (request.getMethod().equals(METHOD_GET) || request.getMethod().equals(METHOD_POST)) {
-				// transfer the content
-				sendFile(fileLocation, response);
-			} else {
-				// anything else cannot be processed on the file
-				// alternatively we could forward to rails, but this
-				// approach is probably more consistent with other web servers
-				response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
-			}
-
-		} catch (NotModifiedException e) {
-			response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
-		} catch (FileNotFoundException e) {
-			response.sendError(HttpServletResponse.SC_NOT_FOUND);
-		} catch (IOException e) {
-			response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
-		}
-	}
-
-	/**
-	 * Send the file, faster, but requires the file is accessible on the file system.
-	 */
-	private void sendFile(File file, HttpServletResponse response) throws IOException {
-		// setup IO streams
-		ByteBuffer buffer = ByteBuffer.allocate(bufferSize);
-		FileChannel in = null;
-		try {
-			in = new FileInputStream(file).getChannel();
-
-			// start returning the response
-			OutputStream out = response.getOutputStream();
-
-			// read the bytes, returning them in the response
-			while (in.read(buffer) != -1) {
-				out.write(buffer.array(), 0, buffer.position());
-				buffer.clear();
-			}
-			out.close();
-		} finally {
-			try {
-				if (in != null) in.close();
-			} catch (IOException ignore) {
-			}
-		}
-	}
-
-	/**
-	 * Return the content-type the would be returned for this file name.
-	 */
-	public String guessContentTypeFromName(String fileName) {
-		// quick hack for types that are necessary, but not handled
-		String lowerName = fileName.toLowerCase();
-		if (lowerName.endsWith(".css")) {
-			return "text/css";
-		} else if (lowerName.endsWith(".js")) {
-			return "text/js";
-		}
-        try {
-            // everything else
-            javax.activation.FileTypeMap typeMap = 
-                javax.activation.FileTypeMap.getDefaultFileTypeMap();
-            return typeMap.getContentType(fileName);
-        } catch (Throwable t) {
-            // allow activation.jar to be missing
-            return "application/octet-stream";
-        }
-	}
-
-	/**
-	 * An exception when the source object has not been modified. While this
-	 * condition is not a failure, it is a break from the normal flow of
-	 * execution.
-	 */
-	private static class NotModifiedException extends IOException {
-		public NotModifiedException() {
-		}
-	}
-
-}
+package org.jruby.webapp;
+
+import org.jruby.webapp.util.FileUtil;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.File;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.io.OutputStream;
+import java.io.FileInputStream;
+import java.util.Calendar;
+import java.util.Date;
+import java.text.SimpleDateFormat;
+import java.nio.channels.FileChannel;
+import java.nio.ByteBuffer;
+
+/**
+ * This servlet returns a static file.
+ *
+ * @author Robert Egglestone
+ */
+public class FileServlet extends HttpServlet {
+
+    private static final String METHOD_DELETE = "DELETE";
+    private static final String METHOD_HEAD = "HEAD";
+    private static final String METHOD_GET = "GET";
+    private static final String METHOD_OPTIONS = "OPTIONS";
+    private static final String METHOD_POST = "POST";
+    private static final String METHOD_PUT = "PUT";
+    private static final String METHOD_TRACE = "TRACE";
+
+	public static final String FALLBACK_SERVLET_PROPERTY = "files.default";
+
+	private static final String[] DEFAULT_WELCOME_FILES = {"index.html", "index.htm"};
+
+	public final static String CACHE_CONTROL_HEADER = "Cache-Control";
+	public final static String EXPIRES_HEADER = "Expires";
+	public final static String DATE_HEADER = "Date";
+
+	private int bufferSize = 1024;
+
+	private File root;
+
+	private String prefix;
+
+	private boolean setCacheHeaders;
+	private int maxAge;
+
+	/**
+	 * A servlet to pass control to if the file does not exist.
+	 */
+
+    private String defaultServletDispatcherName;
+
+	/**
+	 * Initialize the servlet, and determine the webapp root.
+	 */
+	public void init() throws ServletException {
+		prefix = findPrefix();
+		root = findRoot();
+
+		// determine the cache values
+		setCacheHeaders = getServletConfig().getInitParameter("maxAge") != null;
+		if (setCacheHeaders) {
+			maxAge = Integer.parseInt(getServletConfig().getInitParameter("maxAge"));
+		}
+
+		// check for default fallback servlet
+		ServletContext context = getServletContext();
+		String defaultServletName = getServletConfig().getInitParameter("defaultServlet");
+		if (defaultServletName == null) {
+			defaultServletName = context.getInitParameter(FileServlet.FALLBACK_SERVLET_PROPERTY);
+		}
+		if (defaultServletName != null && defaultServletName.length() != 0) {
+            defaultServletDispatcherName = defaultServletName;
+		}
+	}
+
+	/**
+	 * A prefix to prepend on the path when translating from URL to file location, typically "/public".
+	 */
+	protected String findPrefix() {
+		String prefix = getServletContext().getInitParameter("files.prefix");
+		if (prefix == null) prefix = "/public";
+		// prefix must start with a slash if it's specified
+		if (prefix.length() > 0 && !prefix.startsWith("/")) {
+			prefix = "/" + prefix;
+		}
+		return prefix;
+	}
+
+	/**
+	 * Root of the webapp, may be null in which case it is determined from the servlet api.
+	 * The root should be an absolute path that refers to a directory.
+	 */
+	protected File findRoot() throws ServletException {
+		String rootPath = getServletContext().getInitParameter("files.root");
+		if (rootPath == null) {
+			rootPath = FileUtil.getPath(getServletContext(), "/");
+		}
+
+		File root = new File(rootPath);
+		if (!root.isDirectory()) {
+			throw new ServletException("Webapp root does not point to a directory");
+		}
+
+		return root;
+	}
+
+	public String[] getWelcomeFiles() {
+		String[] welcomeFiles;
+
+		String welcomeFilesString = getServletContext().getInitParameter("files.welcome");
+		if (welcomeFilesString != null) {
+			welcomeFiles = parseCommaList(welcomeFilesString);
+		} else {
+			welcomeFiles = DEFAULT_WELCOME_FILES;
+		}
+
+		return welcomeFiles;
+	}
+
+	private String[] parseCommaList(String commaList) {
+		String[] parts = commaList.split(",");
+		for(int i=0; i<parts.length; i++) {
+			parts[i] = parts[i].trim();
+		}
+		return parts;
+	}
+
+	/**
+	 * Look for a file matching the request.
+	 */
+	protected File getFile(HttpServletRequest request) {
+		// find the location of the file
+		String contextPath = request.getContextPath();
+		String relativePath = request.getRequestURI().substring(contextPath.length());
+
+		// normalize the path
+		relativePath = relativePath.replaceAll("\\\\", "/").replaceAll("//", "/");
+
+		// determine the file path to check for
+		String filePath;
+		if (root == null) {
+			filePath = prefix + relativePath;
+		} else {
+			filePath = root.getAbsolutePath() + prefix + relativePath;
+		}
+
+		return getFile(filePath);
+	}
+
+	/**
+	 * Look for a file matching the specified path.
+	 * This should also check default extensions, and for index files in the case of a directory.
+	 */
+	protected File getFile(String filePath) {
+		// try the exact match
+		File fileLocation = getExactFile(filePath);
+		if (fileLocation != null) return fileLocation;
+
+		// try default extension
+		fileLocation = getExactFile(filePath + ".html");
+		if (fileLocation != null) return fileLocation;
+
+		// try welcome files
+		String[] welcomeFiles = getWelcomeFiles();
+		for (int i = 0; i < welcomeFiles.length; i++) {
+
+			fileLocation = getExactFile(filePath + "/" + welcomeFiles[i]);
+			if (fileLocation != null) return fileLocation;
+		}
+
+		// no match was found
+		return null;
+	}
+
+	/**
+	 * Look for a file with this exact path.
+	 */
+	protected File getExactFile(String path) {
+		// try to load the resource
+		File filePath = new File(path);
+		if (!filePath.isFile()) return null;
+		return filePath;
+	}
+
+	private String formatDateForHeader(Date date) {
+	  String safari3OnlyAccessThisStyleDataFormat = "EEE, d MMM yyyy HH:mm:ss z";
+	  return new SimpleDateFormat(safari3OnlyAccessThisStyleDataFormat).format(date);
+	}
+
+	/**
+	 * Transfer the file.
+	 */
+	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+		try {
+			// check the file and open it
+			File fileLocation = getFile(request);
+			if (fileLocation != null) {
+				// file was found, all good
+			} else if (defaultServletDispatcherName != null) {
+				// forward request to the default servlet
+                getServletContext().getNamedDispatcher(defaultServletDispatcherName).forward(request, response);
+				return;
+			} else {
+				// file not found
+				log("File not found: " + request.getRequestURI());
+				throw new FileNotFoundException(request.getRequestURI());
+			}
+
+			// check for modifications
+			long ifModifiedSince = request.getDateHeader("If-Modified-Since");
+			if (ifModifiedSince != -1) {
+				long lastModified = fileLocation.lastModified();
+				if (lastModified == 0) {
+					// last modified date is not known
+				} else if (lastModified < ifModifiedSince) {
+					throw new NotModifiedException();
+				} else {
+					response.setDateHeader("Last-Modified", lastModified);
+				}
+			}
+
+			// set cache headers
+			if (setCacheHeaders) {
+				response.setHeader(CACHE_CONTROL_HEADER, "max-age=" + maxAge);
+				Calendar now = Calendar.getInstance();
+				response.setHeader(DATE_HEADER, formatDateForHeader(now.getTime()));
+				now.add(Calendar.SECOND, maxAge);
+				response.setHeader(EXPIRES_HEADER, formatDateForHeader(now.getTime()));
+			}
+
+			// set the content type
+			String contentType = guessContentTypeFromName(fileLocation.getName());
+			response.setContentType(contentType);
+
+			if (request.getMethod().equals(METHOD_HEAD)) {
+				// head requests don't send the body
+			} else if (request.getMethod().equals(METHOD_GET) || request.getMethod().equals(METHOD_POST)) {
+				// transfer the content
+				sendFile(fileLocation, response);
+			} else {
+				// anything else cannot be processed on the file
+				// alternatively we could forward to rails, but this
+				// approach is probably more consistent with other web servers
+				response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
+			}
+
+		} catch (NotModifiedException e) {
+			response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+		} catch (FileNotFoundException e) {
+			response.sendError(HttpServletResponse.SC_NOT_FOUND);
+		} catch (IOException e) {
+			response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+		}
+	}
+
+	/**
+	 * Send the file, faster, but requires the file is accessible on the file system.
+	 */
+	private void sendFile(File file, HttpServletResponse response) throws IOException {
+		// setup IO streams
+		ByteBuffer buffer = ByteBuffer.allocate(bufferSize);
+		FileChannel in = null;
+		try {
+			in = new FileInputStream(file).getChannel();
+
+			// start returning the response
+			OutputStream out = response.getOutputStream();
+
+			// read the bytes, returning them in the response
+			while (in.read(buffer) != -1) {
+				out.write(buffer.array(), 0, buffer.position());
+				buffer.clear();
+			}
+			out.close();
+		} finally {
+			try {
+				if (in != null) in.close();
+			} catch (IOException ignore) {
+			}
+		}
+	}
+
+	/**
+	 * Return the content-type the would be returned for this file name.
+	 */
+	public String guessContentTypeFromName(String fileName) {
+		// quick hack for types that are necessary, but not handled
+		String lowerName = fileName.toLowerCase();
+		if (lowerName.endsWith(".css")) {
+			return "text/css";
+		} else if (lowerName.endsWith(".js")) {
+			return "text/js";
+		}
+        try {
+            // everything else
+            javax.activation.FileTypeMap typeMap = 
+                javax.activation.FileTypeMap.getDefaultFileTypeMap();
+            return typeMap.getContentType(fileName);
+        } catch (Throwable t) {
+            // allow activation.jar to be missing
+            return "application/octet-stream";
+        }
+	}
+
+	/**
+	 * An exception when the source object has not been modified. While this
+	 * condition is not a failure, it is a break from the normal flow of
+	 * execution.
+	 */
+	private static class NotModifiedException extends IOException {
+		public NotModifiedException() {
+		}
+	}
+
+}

Modified: trunk/rails-integration/src/main/java/org/jruby/webapp/RailsServlet.java (772 => 773)


--- trunk/rails-integration/src/main/java/org/jruby/webapp/RailsServlet.java	2007-10-16 12:32:16 UTC (rev 772)
+++ trunk/rails-integration/src/main/java/org/jruby/webapp/RailsServlet.java	2007-10-17 15:20:11 UTC (rev 773)
@@ -110,12 +110,42 @@
 		return cgiClass.newInstance(cgiArgs, Block.NULL_BLOCK);
 	}
 
+    /*
+     * This ugly hack is because Oracle servlets doesn't handle URIs like
+     * /people;browse correctly. We need to add this manually.
+     */
+    private String addMissingSemiColonParameterForOracle(String requestUriBefore, HttpServletRequest request) {
+        try {
+            java.lang.reflect.Field reqField = request.getClass().getField("requestURI");
+            Object reqData = reqField.get(request);
+            byte[] data = ""
+            int offset = reqData.getClass().getField("offset").getInt(reqData);
+            int length = reqData.getClass().getField("length").getInt(reqData);
+
+            int p = offset+length;
+            int len = data.length;
+            if(p < len && data[p++] == ';') {
+                int start = p;
+                // Delimited by either ? or a space - possibly not a 100% safe
+                while(p < len && data[p] != '?' && data[p] != ' ') {
+                    p++;
+                }
+                return requestUriBefore + ";" + new String(data, start, p-start);
+            }
+        } catch(Throwable e) {}
+        return requestUriBefore;
+    }
+
 	protected void setupEnvironment(Ruby runtime, HttpServletRequest request) {
 		RubyHash env = (RubyHash)runtime.getObject().getConstant("ENV");
 
 		String requestUri = chomp(request.getRequestURI(), "/");
 		if (requestUri.length() == 0) requestUri = "/";
 
+        if(request.getClass().getName().indexOf("EvermindHttpServletRequest") != -1) {
+            requestUri = addMissingSemiColonParameterForOracle(requestUri, request);
+        }
+
 		// RFC3875 The Common Gateway Interface (CGI) Version 1.1
 		setEnv(env, "AUTH_TYPE", request.getAuthType());
 		if (request.getContentLength() != -1) {
_______________________________________________
Jruby-extras-devel mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/jruby-extras-devel

Reply via email to