public boolean execute(Context context) throws Exception {
// ---------------------------------------------------------- Public Methods
// Is there a Tiles Definition to be processed?
ServletActionContext sacontext = (ServletActionContext) context;
ForwardConfig forwardConfig = sacontext.getForwardConfig();
if (forwardConfig == null || forwardConfig.getPath() == null)
{
log.debug("No forwardConfig or no path, so pass to next command.");
return (false);
}
ComponentDefinition definition = null;
try
{
definition = TilesUtil.getDefinition(forwardConfig.getPath(),
sacontext.getRequest(),
sacontext.getContext());
}
catch (FactoryNotFoundException ex)
{
// this is not a serious error, so log at low priority
log.debug("Tiles DefinitionFactory not found, so pass to next command.");
return false;
}
catch (NoSuchDefinitionException ex)
{
// ignore not found
log.debug("NoSuchDefinitionException " + ex.getMessage());
}
// Do we do a forward (original behavior) or an include ?
boolean doInclude = false;
ComponentContext tileContext = null;
// Get current tile context if any.
// If context exists, or if the response has already been committed we will do an include
tileContext = ComponentContext.getContext(sacontext.getRequest());
doInclude = (tileContext != null || sacontext.getResponse().isCommitted());
// Controller associated to a definition, if any
Controller controller = null;
// Computed uri to include
String uri = null;
if (definition != null)
{
// We have a "forward config" definition.
// We use it to complete missing attribute in context.
// We also get uri, controller.
uri = definition.getPath();
controller = definition.getOrCreateController();
if (tileContext == null) {
tileContext =
new ComponentContext(definition.getAttributes());
ComponentContext.setContext(tileContext, sacontext.getRequest());
} else {
tileContext.addMissing(definition.getAttributes());
}
}
// Process definition set in Action, if any. This may override the
// values for uri or controller found using the ForwardConfig, and
// may augment the tileContext with additional attributes.
// :FIXME: the class DefinitionsUtil is deprecated, but I can't find
// the intended alternative to use.
definition = DefinitionsUtil.getActionDefinition(sacontext.getRequest());
if (definition != null) { // We have a definition.
// We use it to complete missing attribute in context.
// We also overload uri and controller if set in definition.
if (definition.getPath() != null) {
log.debug("Override forward uri "
+ uri
+ " with action uri "
+ definition.getPath());
uri = definition.getPath();
}
if (definition.getOrCreateController() != null) {
log.debug("Override forward controller with action controller");
controller = definition.getOrCreateController();
}
if (tileContext == null) {
tileContext =
new ComponentContext(definition.getAttributes());
ComponentContext.setContext(tileContext, sacontext.getRequest());
} else {
tileContext.addMissing(definition.getAttributes());
}
}
if (uri == null) {
log.debug("no uri computed, so pass to next command");
return false;
}
// Execute controller associated to definition, if any.
if (controller != null) {
log.trace("Execute controller: " + controller);
controller.execute(
tileContext,
sacontext.getRequest(),
sacontext.getResponse(),
sacontext.getContext());
}
// If request comes from a previous Tile, do an include.
// This allows to insert an action in a Tile.
if (doInclude) {
log.info("Tiles process complete; doInclude with " + uri);
doInclude(sacontext, uri);
} else {
log.info("Tiles process complete; forward to " + uri);
doForward(sacontext, uri);
}
log.debug("Tiles processed, so clearing forward config from context.");
sacontext.setForwardConfig( null );
return (false);
}
If the current ForwardConfig is using "tiles",
perform necessary pre-processing to set up the TilesContext
and substitute a new ForwardConfig which is understandable
to a RequestDispatcher.
Note that if the command finds a previously existing
ComponentContext in the request, then it
infers that it has been called from within another tile,
so instead of changing the ForwardConfig in the chain
Context, the command uses RequestDispatcher
to include the tile, and returns true, indicating that the processing
chain is complete.
|