1 /* 2 * $Id$ 3 * 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the 9 * "License"); you may not use this file except in compliance 10 * with the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, 15 * software distributed under the License is distributed on an 16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 * KIND, either express or implied. See the License for the 18 * specific language governing permissions and limitations 19 * under the License. 20 */ 21 package org.apache.struts.dispatcher; 22 23 import org.apache.struts.action.ActionMapping; 24 import org.apache.struts.chain.contexts.ActionContext; 25 26 import java.util.StringTokenizer; 27 28 /** 29 * This abstract class is a template for choosing the target method that is 30 * named in the list-encoded <code>parameter</code> attribute of the 31 * {@link ActionMapping} that matches a submission parameter. This is useful for 32 * developers who prefer to use many submit buttons, images, or submit links on 33 * a single form and whose related actions exist in a single action. 34 * <p> 35 * For utility purposes, you can use the <code>key=value</code> notation to 36 * alias methods so that they are exposed as different form element names, in 37 * the event of a naming conflict or otherwise. In this example, the 38 * <em>recalc</em> button (via a submission parameter) will invoke the 39 * <code>recalculate</code> method. The security-minded person may find this 40 * feature valuable to obfuscate and not expose the methods. 41 * <p> 42 * The <em>default</em> key is purely optional, but encouraged when nothing 43 * matches (such as the user pressing the enter key). If this is not specified 44 * and no parameters match the list of method keys, the method resolution 45 * returns <code>null</code>. 46 * <p> 47 * The order of the parameters are guaranteed to be iterated in the order 48 * specified. If multiple buttons were accidently submitted, the first match in 49 * the list will be dispatched. 50 * 51 * @version $Rev$ 52 * @since Struts 1.4 53 */ 54 public abstract class AbstractEventMappingDispatcher extends AbstractMappingDispatcher { 55 private static final long serialVersionUID = -8559616664806617100L; 56 57 /** 58 * The method key, if present, to use if other specified method keys do not 59 * match a request parameter. 60 */ 61 protected static final String DEFAULT_METHOD_KEY = "default"; 62 63 /** 64 * Constructs a new dispatcher with the specified method resolver. 65 * 66 * @param methodResolver the method resolver 67 */ 68 public AbstractEventMappingDispatcher(MethodResolver methodResolver) { 69 super(methodResolver); 70 } 71 72 /** 73 * Determines whether the specified method key is a submission parameter. 74 * 75 * @param context the current action context 76 * @param methodKey the method key 77 * @return <code>true</code> if match; otherwise <code>false</code> 78 * @see #resolveMethodName(ActionContext) 79 */ 80 protected abstract boolean isSubmissionParameter(ActionContext context, String methodKey); 81 82 protected final String resolveMethodName(ActionContext context) { 83 // Obtain the mapping parameter 84 String mappingParameter = super.resolveMethodName(context); 85 if (mappingParameter == null) { 86 return null; 87 } 88 89 // Parse it as a comma-separated list 90 StringTokenizer st = new StringTokenizer(mappingParameter, ","); 91 String defaultMethodName = null; 92 93 while (st.hasMoreTokens()) { 94 String methodKey = st.nextToken().trim(); 95 String methodName = methodKey; 96 97 // The key can either be a direct method name or an alias 98 // to a method as indicated by a "key=value" signature 99 int equals = methodKey.indexOf('='); 100 if (equals > -1) { 101 methodName = methodKey.substring(equals + 1).trim(); 102 methodKey = methodKey.substring(0, equals).trim(); 103 } 104 105 // Set the default if it passes by 106 if (methodKey.equals(DEFAULT_METHOD_KEY)) { 107 defaultMethodName = methodName; 108 } 109 110 // Is it a match? 111 if (isSubmissionParameter(context, methodKey)) { 112 return methodName; 113 } 114 } 115 116 return defaultMethodName; 117 } 118 119 }