001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.acting;
018:
019: import org.apache.avalon.framework.configuration.Configuration;
020: import org.apache.avalon.framework.configuration.ConfigurationException;
021: import org.apache.avalon.framework.parameters.Parameters;
022: import org.apache.cocoon.environment.Redirector;
023: import org.apache.cocoon.environment.SourceResolver;
024: import org.apache.cocoon.environment.Request;
025: import org.apache.cocoon.environment.ObjectModelHelper;
026:
027: import java.util.HashMap;
028: import java.util.Map;
029: import java.util.Enumeration;
030: import java.lang.reflect.InvocationTargetException;
031: import java.lang.reflect.Method;
032:
033: /**
034: * The <code>AbstractMultiAction</code> provides a way
035: * to call methods of an action specified by
036: * the <code>method</code> parameter or request parameter.
037: * This can be extremly useful for action-sets or as
038: * action-sets replacement.
039: *
040: * Example:
041: * <input type="submit" name="doSave" value="Save it"/>
042: * will call the method "doSave" of the MultiAction
043: *
044: * @author <a href="mailto:tcurdt@dff.st">Torsten Curdt</a>
045: * @version CVS $Id: AbstractMultiAction.java 433543 2006-08-22 06:22:54Z crossley $
046: */
047: public abstract class AbstractMultiAction extends
048: ConfigurableServiceableAction {
049:
050: private static final String ACTION_METHOD_PREFIX = "do";
051: private static final String ACTION_METHOD_PARAMETER = "method";
052:
053: private HashMap methodIndex;
054:
055: private static final String removePrefix(String name) {
056: int prefixLen = ACTION_METHOD_PREFIX.length();
057: return name.substring(prefixLen, prefixLen + 1).toLowerCase()
058: + name.substring(prefixLen + 1);
059: }
060:
061: public void configure(Configuration conf)
062: throws ConfigurationException {
063: super .configure(conf);
064:
065: try {
066: Method[] methods = this .getClass().getMethods();
067: methodIndex = new HashMap();
068:
069: for (int i = 0; i < methods.length; i++) {
070: String methodName = methods[i].getName();
071: if (methodName.startsWith(ACTION_METHOD_PREFIX)) {
072: String actionName = removePrefix(methodName);
073: methodIndex.put(actionName, methods[i]);
074: if (getLogger().isDebugEnabled()) {
075: getLogger().debug(
076: "registered method \"" + methodName
077: + "\" as action \""
078: + actionName + "\"");
079: }
080: }
081: }
082: } catch (Exception e) {
083: throw new ConfigurationException(
084: "cannot get methods by reflection", e);
085: }
086: }
087:
088: public Map act(Redirector redirector, SourceResolver resolver,
089: Map objectModel, String source, Parameters parameters)
090: throws Exception {
091: String actionMethod = parameters.getParameter(
092: ACTION_METHOD_PARAMETER, null);
093:
094: if (actionMethod == null) {
095: Request req = ObjectModelHelper.getRequest(objectModel);
096: if (req != null) {
097: // checking request for action method parameters
098: String name;
099: for (Enumeration e = req.getParameterNames(); e
100: .hasMoreElements();) {
101: name = (String) e.nextElement();
102: if (name.startsWith(ACTION_METHOD_PREFIX)) {
103: if (name.endsWith(".x") || name.endsWith(".y")) {
104: name = name.substring(ACTION_METHOD_PREFIX
105: .length(), name.length() - 2);
106: }
107: actionMethod = removePrefix(name);
108: break;
109: }
110: }
111: }
112: }
113:
114: if ((actionMethod != null) && (actionMethod.length() > 0)) {
115: Method method = (Method) methodIndex.get(actionMethod);
116: if (method != null) {
117: try {
118: return ((Map) method.invoke(this , new Object[] {
119: redirector, resolver, objectModel, source,
120: parameters }));
121: } catch (InvocationTargetException ite) {
122: if ((ite.getTargetException() != null)
123: && (ite.getTargetException() instanceof Exception)) {
124: throw (Exception) ite.getTargetException();
125: } else {
126: throw ite;
127: }
128: }
129: } else {
130: throw new Exception("action has no method \""
131: + actionMethod + "\"");
132: }
133: }
134:
135: if (getLogger().isDebugEnabled()) {
136: getLogger()
137: .debug(
138: "you need to specify the method with parameter \""
139: + ACTION_METHOD_PARAMETER
140: + "\" or have a request parameter starting with \""
141: + ACTION_METHOD_PREFIX + "\"");
142: }
143: return null;
144: }
145: }
|