All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jodd.madvoc.component.MadvocController Maven / Gradle / Ivy

// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

package jodd.madvoc.component;

import jodd.log.Logger;
import jodd.log.LoggerFactory;
import jodd.madvoc.ActionRequest;
import jodd.madvoc.MadvocException;
import jodd.madvoc.MadvocUtil;
import jodd.madvoc.config.ActionRuntime;
import jodd.madvoc.result.ActionResult;
import jodd.petite.meta.PetiteInject;
import jodd.servlet.ServletUtil;
import jodd.util.ClassUtil;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Madvoc controller invokes actions for action path and renders action results.
 * It also builds action objects and result paths. It handles initialization of
 * interceptors and results.
 */
public class MadvocController extends MadvocControllerCfg implements MadvocComponentLifecycle.Ready{

	private static final Logger log = LoggerFactory.getLogger(MadvocController.class);

	@PetiteInject
	protected MadvocEncoding madvocEncoding;

	@PetiteInject
	protected ActionsManager actionsManager;

	@PetiteInject
	protected ActionPathRewriter actionPathRewriter;

	@PetiteInject
	protected ResultsManager resultsManager;

	@PetiteInject
	protected ServletContextProvider servletContextProvider;

	@PetiteInject
	protected AsyncActionExecutor asyncActionExecutor;

	@Override
	public void ready() {
		if (actionsManager.isAsyncModeOn()) {
			asyncActionExecutor.start();
		}
	}

	/**
	 * Returns application context set during the initialization.
	 */
	public ServletContext getApplicationContext() {
		return servletContextProvider.get();
	}

	// ---------------------------------------------------------------- invoke


	/**
	 * Invokes action registered to provided action path, Provides action chaining, by invoking the next action request.
	 * Returns null if action path is consumed and has been invoked by this controller; otherwise
	 * the action path string is returned (it might be different than original one, provided in arguments).
	 * On first invoke, initializes the action runtime before further proceeding.
	 */
	public String invoke(String actionPath, final HttpServletRequest servletRequest, final HttpServletResponse servletResponse) throws Exception {
		final String originalActionPath = actionPath;
		boolean characterEncodingSet = false;

		while (actionPath != null) {
			// build action path
			final String httpMethod = servletRequest.getMethod().toUpperCase();

			if (log.isDebugEnabled()) {
				log.debug("Action path: " + httpMethod + " " + actionPath);
			}

			actionPath = actionPathRewriter.rewrite(servletRequest, actionPath, httpMethod);

			String[] actionPathChunks = MadvocUtil.splitPathToChunks(actionPath);

			// resolve action runtime
			ActionRuntime actionRuntime = actionsManager.lookup(httpMethod, actionPathChunks);

			if (actionRuntime == null) {

				// special case!
				if (actionPath.endsWith(welcomeFile)) {
					actionPath = actionPath.substring(0, actionPath.length() - (welcomeFile.length() - 1));
					actionPathChunks = MadvocUtil.splitPathToChunks(actionPath);
					actionRuntime = actionsManager.lookup(httpMethod, actionPathChunks);
				}
				if (actionRuntime == null) {
					return originalActionPath;
				}
			}
			if (log.isDebugEnabled()) {
				log.debug("Invoke action for '" + actionPath + "' using " + actionRuntime.createActionString());
			}

			// set character encoding
			if (!characterEncodingSet && applyCharacterEncoding) {

				final String encoding = madvocEncoding.getEncoding();

				if (encoding != null) {
					servletRequest.setCharacterEncoding(encoding);
					servletResponse.setCharacterEncoding(encoding);
				}

				characterEncodingSet = true;
			}

			// create action object
			final Object action;

			if (actionRuntime.isActionHandlerDefined()) {
				action = actionRuntime.getActionHandler();
			}
			else {
				action = createAction(actionRuntime.getActionClass());
			}

			final ActionRequest actionRequest = createActionRequest(
				actionPath,
				actionPathChunks,
				actionRuntime,
				action,
				servletRequest,
				servletResponse);

			// invoke and render
			if (actionRuntime.isAsync()) {
				asyncActionExecutor.invoke(actionRequest);
			} else {
				actionRequest.invoke();
			}

			actionPath = actionRequest.getNextActionPath();
		}
		return null;
	}


	// ---------------------------------------------------------------- render

	/**
	 * Invokes a result after the action invocation.
	 * 

* Results may be objects that specify which action result will be used * to render the result. *

* Result value may consist of two parts: type and value. Result type is optional and, if exists, it is separated * by semi-colon from the value. If type is not specified * then the default result type if still not defined. Result type defines which * {@link ActionResult} should be used for rendering the value. *

* Result value is first checked against aliased values. Then, it is resolved and then passed * to the founded {@link ActionResult}. * * @see ActionResult#render(jodd.madvoc.ActionRequest, Object) */ @SuppressWarnings("unchecked") public void render(final ActionRequest actionRequest, final Object resultObject) throws Exception { final ActionResult actionResult = resultsManager.lookup(actionRequest, resultObject); if (actionResult == null) { throw new MadvocException("Action result not found"); } if (preventCaching) { ServletUtil.preventCaching(actionRequest.getHttpServletResponse()); } log.debug(() -> "Result type: " + actionResult.getClass().getSimpleName()); actionResult.render(actionRequest, actionRequest.getActionResult()); } // ---------------------------------------------------------------- create /** * Creates new action object from {@link ActionRuntime} using default constructor. */ protected Object createAction(final Class actionClass) { try { return ClassUtil.newInstance(actionClass); } catch (Exception ex) { throw new MadvocException("Invalid Madvoc action", ex); } } /** * Creates new action request. * @param actionPath action path * @param actionRuntime action runtime * @param action action object * @param servletRequest http request * @param servletResponse http response * @return action request */ protected ActionRequest createActionRequest( final String actionPath, final String[] actionPathChunks, final ActionRuntime actionRuntime, final Object action, final HttpServletRequest servletRequest, final HttpServletResponse servletResponse) { return new ActionRequest(this, actionPath, actionPathChunks, actionRuntime, action, servletRequest, servletResponse); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy