KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > struts > config > ActionConfigMatcher


1 /*
2  * $Id: ActionConfigMatcher.java 54929 2004-10-16 16:38:42Z germuska $
3  *
4  * Copyright 2003,2004 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18  
19 package org.apache.struts.config;
20
21 import java.io.Serializable JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.Map JavaDoc;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30
31 import org.apache.commons.beanutils.BeanUtils;
32
33 import org.apache.struts.action.ActionForward;
34 import org.apache.struts.util.WildcardHelper;
35
36 /**
37  * Matches paths against pre-compiled wildcard expressions pulled from
38  * action configs. It uses the wildcard matcher from the Apache
39  * Cocoon project.
40  *
41  * @since Struts 1.2
42  */

43 public class ActionConfigMatcher implements Serializable JavaDoc {
44
45     /**
46      * The logging instance
47      */

48     private static final Log log =
49         LogFactory.getLog(ActionConfigMatcher.class);
50         
51     /**
52      * Handles all wildcard pattern matching.
53      */

54     private static final WildcardHelper wildcard = new WildcardHelper();
55     
56     /**
57      * The compiled paths and their associated ActionConfig's
58      */

59     private List JavaDoc compiledPaths;
60
61     /**
62      * Finds and precompiles the wildcard patterns from the ActionConfig
63      * "path" attributes.
64      * ActionConfig's will be evaluated in the order they exist in the
65      * Struts config file. Only paths that actually contain a wildcard
66      * will be compiled.
67      *
68      * @param configs An array of ActionConfig's to process
69      */

70     public ActionConfigMatcher(ActionConfig[] configs) {
71         compiledPaths = new ArrayList JavaDoc();
72         int[] pattern;
73         String JavaDoc path;
74         for (int x = 0; x < configs.length; x++) {
75             path = configs[x].getPath();
76             if (path != null && path.indexOf('*') > -1) {
77                 if (path.length() > 0 && path.charAt(0) == '/') {
78                     path = path.substring(1);
79                 }
80                 if (log.isDebugEnabled()) {
81                     log.debug("Compiling action config path '" + path + "'");
82                 }
83                 pattern = wildcard.compilePattern(path);
84                 compiledPaths.add(new Mapping(pattern, configs[x]));
85             }
86         }
87     }
88
89     /**
90      * Matches the path against the compiled wildcard patterns.
91      *
92      * @param path The portion of the request URI for selecting a config.
93      * @return The action config if matched, else null
94      */

95     public ActionConfig match(String JavaDoc path) {
96
97         ActionConfig config = null;
98         if (compiledPaths.size() > 0) {
99             if (log.isDebugEnabled()) {
100                 log.debug("Attempting to match '" + path
101                     + "' to a wildcard pattern");
102             }
103             if (path.length() > 0 && path.charAt(0) == '/') {
104                 path = path.substring(1);
105             }
106             Mapping m;
107             HashMap JavaDoc vars = new HashMap JavaDoc();
108             for (Iterator JavaDoc i = compiledPaths.iterator(); i.hasNext();) {
109                 m = (Mapping) i.next();
110                 if (wildcard.match(vars, path, m.getPattern())) {
111                     config = convertActionConfig(
112                             path,
113                             (ActionConfig) m.getActionConfig(),
114                             vars);
115                 }
116             }
117         }
118
119         return config;
120     }
121     
122     /**
123      * Clones the ActionConfig and its children, replacing various properties
124      * with the values of the wildcard-matched strings.
125      *
126      * @param path The requested path
127      * @param orig The original ActionConfig
128      * @param vars A Map of wildcard-matched strings
129      * @return A cloned ActionConfig with appropriate properties replaced
130      * with wildcard-matched values
131      */

132     protected ActionConfig convertActionConfig(String JavaDoc path,
133             ActionConfig orig, Map JavaDoc vars) {
134         ActionConfig config = null;
135         
136         try {
137             config = (ActionConfig) BeanUtils.cloneBean(orig);
138         }
139         catch (Exception JavaDoc ex) {
140             log.warn("Unable to clone action config, recommend not using "
141                 + "wildcards", ex);
142             return null;
143         }
144         
145         config.setName(convertParam(orig.getName(), vars));
146         if (path.length() == 0 || path.charAt(0) != '/') {
147             path = "/" + path;
148         }
149         config.setPath(path);
150         config.setType(convertParam(orig.getType(), vars));
151         config.setRoles(convertParam(orig.getRoles(), vars));
152         config.setParameter(convertParam(orig.getParameter(), vars));
153         config.setAttribute(convertParam(orig.getAttribute(), vars));
154         config.setForward(convertParam(orig.getForward(), vars));
155         config.setInclude(convertParam(orig.getInclude(), vars));
156         config.setInput(convertParam(orig.getInput(), vars));
157
158         ForwardConfig[] fConfigs = orig.findForwardConfigs();
159         ForwardConfig cfg;
160         for (int x = 0; x < fConfigs.length; x++) {
161             cfg = new ActionForward();
162             cfg.setContextRelative(fConfigs[x].getContextRelative());
163             cfg.setName(fConfigs[x].getName());
164             cfg.setPath(convertParam(fConfigs[x].getPath(), vars));
165             cfg.setRedirect(fConfigs[x].getRedirect());
166             config.removeForwardConfig(fConfigs[x]);
167             config.addForwardConfig(cfg);
168         }
169         
170         ExceptionConfig[] exConfigs = orig.findExceptionConfigs();
171         for (int x = 0; x < exConfigs.length; x++) {
172             config.addExceptionConfig(exConfigs[x]);
173         }
174         
175         config.freeze();
176         
177         return config;
178     }
179
180     /**
181      * Inserts into a value wildcard-matched strings where specified.
182      *
183      * @param val The value to convert
184      * @param vars A Map of wildcard-matched strings
185      * @return The new value
186      */

187     protected String JavaDoc convertParam(String JavaDoc val, Map JavaDoc vars) {
188         if (val == null) {
189             return null;
190         } else if (val.indexOf("{") == -1) {
191             return val;
192         }
193
194         Map.Entry JavaDoc entry;
195         StringBuffer JavaDoc key = new StringBuffer JavaDoc("{0}");
196         StringBuffer JavaDoc ret = new StringBuffer JavaDoc(val);
197         String JavaDoc keyTmp;
198         int x;
199         for (Iterator JavaDoc i = vars.entrySet().iterator(); i.hasNext();) {
200             entry = (Map.Entry JavaDoc) i.next();
201             key.setCharAt(1, ((String JavaDoc) entry.getKey()).charAt(0));
202             keyTmp = key.toString();
203             
204             // Replace all instances of the placeholder
205
while ((x = ret.toString().indexOf(keyTmp)) > -1) {
206                 ret.replace(x, x + 3, (String JavaDoc) entry.getValue());
207             }
208         }
209         return ret.toString();
210     }
211
212     /**
213      * Stores a compiled wildcard pattern and the ActionConfig it came from.
214      */

215     private class Mapping implements Serializable JavaDoc {
216
217         /** The compiled pattern. */
218         private int[] pattern;
219
220         /** The original ActionConfig. */
221         private ActionConfig config;
222
223         /**
224          * Contructs a read-only Mapping instance.
225          *
226          * @param pattern The compiled pattern
227          * @param config The original ActionConfig
228          */

229         public Mapping(int[] pattern, ActionConfig config) {
230             this.pattern = pattern;
231             this.config = config;
232         }
233
234         /**
235          * Gets the compiled wildcard pattern.
236          *
237          * @return The compiled pattern
238          */

239         public int[] getPattern() {
240             return this.pattern;
241         }
242
243         /**
244          * Gets the ActionConfig that contains the pattern.
245          *
246          * @return The associated ActionConfig
247          */

248         public ActionConfig getActionConfig() {
249             return this.config;
250         }
251     }
252 }
253
254
Popular Tags