blob: ca7ae0ce2ecd337579005e76eeed8edad2abb657 [file] [log] [blame]
/*
* $Id$
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.struts.chain.commands;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.chain.Constants;
import org.apache.struts.chain.commands.util.ClassUtils;
import org.apache.struts.chain.contexts.ActionContext;
import org.apache.struts.config.ActionConfig;
import org.apache.struts.config.ForwardConfig;
import org.apache.struts.dispatcher.Dispatcher;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class ExecuteDispatcher extends ActionCommandBase {
private static final Log log = LogFactory.getLog(ExecuteDispatcher.class);
/**
* Creates the dispatcher of the specified type.
*
* @param type the dispatcher class name
* @param context the current action context
* @return the dispatcher
* @throws Exception if creation fails
* @see ClassUtils#getApplicationInstance(String)
*/
protected Dispatcher createDispatcher(String type, ActionContext context) throws Exception {
log.info("Initializing dispatcher of type: " + type);
return (Dispatcher) ClassUtils.getApplicationInstance(type);
}
public boolean execute(ActionContext context) throws Exception {
// Skip processing if the current request is not valid
Boolean valid = context.getFormValid();
if ((valid == null) || !valid.booleanValue()) {
return CONTINUE_PROCESSING;
}
// Skip processing if no dispatcher type specified
String dispatcherType = getDispatcherType(context);
if (dispatcherType == null) {
return CONTINUE_PROCESSING;
}
// Obtain (or create) the dispatcher cache
String cacheKey = Constants.DISPATCHERS_KEY + context.getModuleConfig().getPrefix();
Map dispatchers = (Map) context.getApplicationScope().get(cacheKey);
if (dispatchers == null) {
dispatchers = new HashMap();
context.getApplicationScope().put(cacheKey, dispatchers);
}
// Lookup (or create) the dispatch instance
Dispatcher dispatcher = null;
synchronized (dispatchers) {
ActionConfig actionConfig = context.getActionConfig();
String actionType = actionConfig.getType();
dispatcher = (Dispatcher) dispatchers.get(actionType);
if (dispatcher == null) {
dispatcher = createDispatcher(dispatcherType, context);
dispatchers.put(actionType, dispatcher);
}
}
// Dispatch
Object result = dispatcher.dispatch(context);
processDispatchResult(result, context);
return CONTINUE_PROCESSING;
}
protected String getDispatcherType(ActionContext context) {
return (context != null) ? context.getActionConfig().getDispatcher() : null;
}
/**
* Interprets the specified dispatch result. Subclasses should override this
* method to provide custom result type handling. Four handlings are
* automatically provided:
* <ol>
* <li><code>null</code> type means the response was handled directly,
* and therefore no extra processing is perform</li>
* <li>{@link ForwardConfig} type is the classical response, and will be
* stored in the context</li>
* <li>{@link String} type represents the name of a required forward to
* lookup, and will be stored in the context</li>
* <li>{@link Void} type means the method had no return signature, and
* select the {@link Action#SUCCESS} action forward and store in the context</li>
* </ol>
*
* @param result the result value
* @param context the current action context
* @throws IllegalStateException if unknown result type or the forward
* cannot be found
* @see ActionMapping#findRequiredForward(String)
*/
protected void processDispatchResult(Object result, ActionContext context) {
// Null means the response was handled directly
if (result == null) {
return;
}
// A forward is the classical response
if (result instanceof ForwardConfig) {
context.setForwardConfig((ForwardConfig) result);
return;
}
// String represents the name of a forward
ActionConfig actionConfig = context.getActionConfig();
ActionMapping mapping = ((ActionMapping) actionConfig);
if (result instanceof String) {
context.setForwardConfig(mapping.findRequiredForward((String) result));
return;
}
// Select success if no return signature
if (result instanceof Void) {
context.setForwardConfig(mapping.findRequiredForward(Action.SUCCESS));
return;
}
// Unknown result type
throw new IllegalStateException("Unknown dispatch return type: " + result.getClass().getName());
}
}