1 /*
2 * Copyright (c) 2002-2006 by OpenSymphony
3 * All rights reserved.
4 */
5 package com.opensymphony.xwork2.config.providers;
6
7 import com.opensymphony.xwork2.ObjectFactory;
8 import com.opensymphony.xwork2.config.ConfigurationException;
9 import com.opensymphony.xwork2.config.entities.InterceptorConfig;
10 import com.opensymphony.xwork2.config.entities.InterceptorLocator;
11 import com.opensymphony.xwork2.config.entities.InterceptorMapping;
12 import com.opensymphony.xwork2.config.entities.InterceptorStackConfig;
13 import com.opensymphony.xwork2.interceptor.Interceptor;
14 import com.opensymphony.xwork2.util.location.Location;
15 import com.opensymphony.xwork2.util.logging.Logger;
16 import com.opensymphony.xwork2.util.logging.LoggerFactory;
17
18 import java.util.ArrayList;
19 import java.util.LinkedHashMap;
20 import java.util.List;
21 import java.util.Map;
22
23
24 /**
25 * Builds a list of interceptors referenced by the refName in the supplied PackageConfig.
26 *
27 * @author Mike
28 * @author Rainer Hermanns
29 * @author tmjee
30 * @version $Date: 2008-06-21 11:29:39 +0200 (Sa, 21 Jun 2008) $ $Id: InterceptorBuilder.java 1833 2008-06-21 09:29:39Z rainerh $
31 */
32 public class InterceptorBuilder {
33
34 private static final Logger LOG = LoggerFactory.getLogger(InterceptorBuilder.class);
35
36
37 /**
38 * Builds a list of interceptors referenced by the refName in the supplied PackageConfig (InterceptorMapping object).
39 *
40 * @param interceptorLocator
41 * @param refName
42 * @param refParams
43 * @return list of interceptors referenced by the refName in the supplied PackageConfig (InterceptorMapping object).
44 * @throws ConfigurationException
45 */
46 public static List<InterceptorMapping> constructInterceptorReference(InterceptorLocator interceptorLocator,
47 String refName, Map<String,String> refParams, Location location, ObjectFactory objectFactory) throws ConfigurationException {
48 Object referencedConfig = interceptorLocator.getInterceptorConfig(refName);
49 List<InterceptorMapping> result = new ArrayList<InterceptorMapping>();
50
51 if (referencedConfig == null) {
52 throw new ConfigurationException("Unable to find interceptor class referenced by ref-name " + refName, location);
53 } else {
54 if (referencedConfig instanceof InterceptorConfig) {
55 InterceptorConfig config = (InterceptorConfig) referencedConfig;
56 Interceptor inter = null;
57 try {
58
59 inter = objectFactory.buildInterceptor(config, refParams);
60 result.add(new InterceptorMapping(refName, inter));
61 } catch (ConfigurationException ex) {
62 LOG.warn("Unable to load config class " + config.getClassName() + " at " +
63 ex.getLocation() + " probably due to a missing jar, which might " +
64 "be fine if you never plan to use the " + config.getName() + " interceptor");
65 LOG.error("Actual exception", ex);
66 }
67
68 } else if (referencedConfig instanceof InterceptorStackConfig) {
69 InterceptorStackConfig stackConfig = (InterceptorStackConfig) referencedConfig;
70
71 if ((refParams != null) && (refParams.size() > 0)) {
72 result = constructParameterizedInterceptorReferences(interceptorLocator, stackConfig, refParams, objectFactory);
73 } else {
74 result.addAll(stackConfig.getInterceptors());
75 }
76
77 } else {
78 LOG.error("Got unexpected type for interceptor " + refName + ". Got " + referencedConfig);
79 }
80 }
81
82 return result;
83 }
84
85 /**
86 * Builds a list of interceptors referenced by the refName in the supplied PackageConfig overriding the properties
87 * of the referenced interceptor with refParams.
88 *
89 * @param interceptorLocator
90 * @param stackConfig
91 * @param refParams The overridden interceptor properies
92 * @return list of interceptors referenced by the refName in the supplied PackageConfig overridden with refParams.
93 */
94 private static List<InterceptorMapping> constructParameterizedInterceptorReferences(
95 InterceptorLocator interceptorLocator, InterceptorStackConfig stackConfig, Map<String,String> refParams,
96 ObjectFactory objectFactory) {
97 List<InterceptorMapping> result;
98 Map<String, Map<String, String>> params = new LinkedHashMap<String, Map<String, String>>();
99
100 /*
101 * We strip
102 *
103 * <interceptor-ref name="someStack">
104 * <param name="interceptor1.param1">someValue</param>
105 * <param name="interceptor1.param2">anotherValue</param>
106 * </interceptor-ref>
107 *
108 * down to map
109 * interceptor1 -> [param1 -> someValue, param2 -> anotherValue]
110 *
111 * or
112 * <interceptor-ref name="someStack">
113 * <param name="interceptorStack1.interceptor1.param1">someValue</param>
114 * <param name="interceptorStack1.interceptor1.param2">anotherValue</param>
115 * </interceptor-ref>
116 *
117 * down to map
118 * interceptorStack1 -> [interceptor1.param1 -> someValue, interceptor1.param2 -> anotherValue]
119 *
120 */
121 for (String key : refParams.keySet()) {
122 String value = refParams.get(key);
123
124 try {
125 String name = key.substring(0, key.indexOf('.'));
126 key = key.substring(key.indexOf('.') + 1);
127
128 Map<String, String> map;
129 if (params.containsKey(name)) {
130 map = params.get(name);
131 } else {
132 map = new LinkedHashMap<String, String>();
133 }
134
135 map.put(key, value);
136 params.put(name, map);
137
138 } catch (Exception e) {
139 LOG.warn("No interceptor found for name = " + key);
140 }
141 }
142
143 result = new ArrayList<InterceptorMapping>(stackConfig.getInterceptors());
144
145 for (String key : params.keySet()) {
146
147 Map<String, String> map = params.get(key);
148
149
150 Object interceptorCfgObj = interceptorLocator.getInterceptorConfig(key);
151
152 /*
153 * Now we attempt to separate out param that refers to Interceptor
154 * and Interceptor stack, eg.
155 *
156 * <interceptor-ref name="someStack">
157 * <param name="interceptor1.param1">someValue</param>
158 * ...
159 * </interceptor-ref>
160 *
161 * vs
162 *
163 * <interceptor-ref name="someStack">
164 * <param name="interceptorStack1.interceptor1.param1">someValue</param>
165 * ...
166 * </interceptor-ref>
167 */
168 if (interceptorCfgObj instanceof InterceptorConfig) { // interceptor-ref param refer to an interceptor
169 InterceptorConfig cfg = (InterceptorConfig) interceptorCfgObj;
170 Interceptor interceptor = objectFactory.buildInterceptor(cfg, map);
171
172 InterceptorMapping mapping = new InterceptorMapping(key, interceptor);
173 if (result != null && result.contains(mapping)) {
174 // if an existing interceptor mapping exists,
175 // we remove from the result Set, just to make sure
176 // there's always one unique mapping.
177 int index = result.indexOf(mapping);
178 result.set(index, mapping);
179 } else {
180 result.add(mapping);
181 }
182 } else
183 if (interceptorCfgObj instanceof InterceptorStackConfig) { // interceptor-ref param refer to an interceptor stack
184
185 // If its an interceptor-stack, we call this method recursively untill,
186 // all the params (eg. interceptorStack1.interceptor1.param etc.)
187 // are resolved down to a specific interceptor.
188
189 InterceptorStackConfig stackCfg = (InterceptorStackConfig) interceptorCfgObj;
190 List<InterceptorMapping> tmpResult = constructParameterizedInterceptorReferences(interceptorLocator, stackCfg, map, objectFactory);
191 for (InterceptorMapping tmpInterceptorMapping : tmpResult) {
192 if (result.contains(tmpInterceptorMapping)) {
193 int index = result.indexOf(tmpInterceptorMapping);
194 result.set(index, tmpInterceptorMapping);
195 } else {
196 result.add(tmpInterceptorMapping);
197 }
198 }
199 }
200 }
201
202 return result;
203 }
204 }