@SuppressWarnings("rawtypes")
	protected void processRequest(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		String[] splitString = request.getPathInfo().split("/");
		String actionString = (splitString == null) ? null : splitString[1];
		if (actionString == null) {
			throw new IllegalArgumentException("Parameter named action must "
					+ "be provided");
		}

		String shortControllerClassName = StringUtils.convertSnakeToCamelCase(
				actionString, true);
		String fullControllerClassName = packagePrefix + "controllers."
				+ StringUtils.convertSnakeToCamelCase(actionString, true)
				+ "Controller";
		String controllerMethodName = "index"; // default value

		if (splitString.length > 2) {
			controllerMethodName = splitString[2];
		}

		logger.log(Level.FINE, "packagePrefix {0}", packagePrefix);
		logger.log(Level.FINE, "controllerClassName {0}",
				shortControllerClassName);
		logger.log(Level.FINE, "controllerMethodName {0}", controllerMethodName);

		try {

			ActionContext ac = new ActionContext(
					shortControllerClassName.toLowerCase() + "."
							+ controllerMethodName.toLowerCase(), request);
			if (isControllerExists(fullControllerClassName)) {
				// call any controller method
				Class c = Class.forName(fullControllerClassName);

				Object obj = controllers.get(fullControllerClassName);

				try {
					@SuppressWarnings("unchecked")
					Method method = c.getMethod(controllerMethodName,
							ActionContext.class);

					method.invoke(obj, ac);
				} catch (NoSuchMethodException nsme) {
					// method doesn't exist, so nothing to do
				}
			}

			request.setAttribute("rc", ac.getRc());

			if (ac.getRedirectTo() != null) {
				response.sendRedirect(Framework.createHref(request.getContextPath(), this.actionPath, ac.getRedirectTo()));
				return;
			}

			/*
			 * Look for 3 levels of layout. - layouts/section/item.jsp: The
			 * view-specific layout (required) - layouts/section.jsp: The
			 * section-specific layout (optional) - layouts/default.jsp: The
			 * site-wide layout (required)
			 */

			String viewSpecificLayout = "/WEB-INF/views/" + ac.getViewSection()
					+ "/" + ac.getViewItem() + ".jsp";
			String sectionSpecificLayout = "/WEB-INF/layouts/"
					+ ac.getViewSection() + ".jsp";
			String defaultLayout = "/WEB-INF/layouts/default.jsp";

			if (getServletContext().getResource(sectionSpecificLayout) != null) {
				request.setAttribute("viewSpecificLayout", viewSpecificLayout);
				request.setAttribute("sectionSpecificLayout",
						sectionSpecificLayout);
			} else {
				request.setAttribute("viewSpecificLayout", viewSpecificLayout);
				request.setAttribute("sectionSpecificLayout", null);
			}

			request.getRequestDispatcher(defaultLayout).include(request,
					response);

		} catch (Exception ex) {
			logger.log(Level.SEVERE, null, ex);
			throw new ServletException(ex.getMessage(), ex);
		}
	}