/*
* Copyright 2002-2006,2009 The Apache Software Foundation.
*
* Licensed 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 com.opensymphony.xwork2.config.providers;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.config.entities.InterceptorConfig;
import com.opensymphony.xwork2.config.entities.InterceptorLocator;
import com.opensymphony.xwork2.config.entities.InterceptorMapping;
import com.opensymphony.xwork2.config.entities.InterceptorStackConfig;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.util.location.Location;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Builds a list of interceptors referenced by the refName in the supplied PackageConfig.
*
* @author Mike
* @author Rainer Hermanns
* @author tmjee
* @version $Date$ $Id$
*/
public class InterceptorBuilder {
private static final Logger LOG = LoggerFactory.getLogger(InterceptorBuilder.class);
/**
* Builds a list of interceptors referenced by the refName in the supplied PackageConfig (InterceptorMapping object).
*
* @param interceptorLocator
* @param refName
* @param refParams
* @return list of interceptors referenced by the refName in the supplied PackageConfig (InterceptorMapping object).
* @throws ConfigurationException
*/
public static List<InterceptorMapping> constructInterceptorReference(InterceptorLocator interceptorLocator,
String refName, Map<String,String> refParams, Location location, ObjectFactory objectFactory) throws ConfigurationException {
Object referencedConfig = interceptorLocator.getInterceptorConfig(refName);
List<InterceptorMapping> result = new ArrayList<InterceptorMapping>();
if (referencedConfig == null) {
throw new ConfigurationException("Unable to find interceptor class referenced by ref-name " + refName, location);
} else {
if (referencedConfig instanceof InterceptorConfig) {
InterceptorConfig config = (InterceptorConfig) referencedConfig;
Interceptor inter = null;
try {
inter = objectFactory.buildInterceptor(config, refParams);
result.add(new InterceptorMapping(refName, inter));
} catch (ConfigurationException ex) {
if (LOG.isWarnEnabled()) {
LOG.warn("Unable to load config class #0 at #1 probably due to a missing jar, which might be fine if you never plan to use the #2 interceptor",
config.getClassName(), ex.getLocation().toString(), config.getName());
}
LOG.error("Actual exception", ex);
}
} else if (referencedConfig instanceof InterceptorStackConfig) {
InterceptorStackConfig stackConfig = (InterceptorStackConfig) referencedConfig;
if ((refParams != null) && (refParams.size() > 0)) {
result = constructParameterizedInterceptorReferences(interceptorLocator, stackConfig, refParams, objectFactory);
} else {
result.addAll(stackConfig.getInterceptors());
}
} else {
LOG.error("Got unexpected type for interceptor " + refName + ". Got " + referencedConfig);
}
}
return result;
}
/**
* Builds a list of interceptors referenced by the refName in the supplied PackageConfig overriding the properties
* of the referenced interceptor with refParams.
*
* @param interceptorLocator
* @param stackConfig
* @param refParams The overridden interceptor properies
* @return list of interceptors referenced by the refName in the supplied PackageConfig overridden with refParams.
*/
private static List<InterceptorMapping> constructParameterizedInterceptorReferences(
InterceptorLocator interceptorLocator, InterceptorStackConfig stackConfig, Map<String,String> refParams,
ObjectFactory objectFactory) {
List<InterceptorMapping> result;
Map<String, Map<String, String>> params = new LinkedHashMap<String, Map<String, String>>();
/*
* We strip
*
* <interceptor-ref name="someStack">
* <param name="interceptor1.param1">someValue</param>
* <param name="interceptor1.param2">anotherValue</param>
* </interceptor-ref>
*
* down to map
* interceptor1 -> [param1 -> someValue, param2 -> anotherValue]
*
* or
* <interceptor-ref name="someStack">
* <param name="interceptorStack1.interceptor1.param1">someValue</param>
* <param name="interceptorStack1.interceptor1.param2">anotherValue</param>
* </interceptor-ref>
*
* down to map
* interceptorStack1 -> [interceptor1.param1 -> someValue, interceptor1.param2 -> anotherValue]
*
*/
for (String key : refParams.keySet()) {
String value = refParams.get(key);
try {
String name = key.substring(0, key.indexOf('.'));
key = key.substring(key.indexOf('.') + 1);
Map<String, String> map;
if (params.containsKey(name)) {
map = params.get(name);
} else {
map = new LinkedHashMap<String, String>();
}
map.put(key, value);
params.put(name, map);
} catch (Exception e) {
if (LOG.isWarnEnabled()) {
LOG.warn("No interceptor found for name = #0", key);
}
}
}
result = new ArrayList<InterceptorMapping>(stackConfig.getInterceptors());
for (String key : params.keySet()) {
Map<String, String> map = params.get(key);
Object interceptorCfgObj = interceptorLocator.getInterceptorConfig(key);
/*
* Now we attempt to separate out param that refers to Interceptor
* and Interceptor stack, eg.
*
* <interceptor-ref name="someStack">
* <param name="interceptor1.param1">someValue</param>
* ...
* </interceptor-ref>
*
* vs
*
* <interceptor-ref name="someStack">
* <param name="interceptorStack1.interceptor1.param1">someValue</param>
* ...
* </interceptor-ref>
*/
if (interceptorCfgObj instanceof InterceptorConfig) { // interceptor-ref param refer to an interceptor
InterceptorConfig cfg = (InterceptorConfig) interceptorCfgObj;
Interceptor interceptor = objectFactory.buildInterceptor(cfg, map);
InterceptorMapping mapping = new InterceptorMapping(key, interceptor);
if (result != null && result.contains(mapping)) {
// if an existing interceptor mapping exists,
// we remove from the result Set, just to make sure
// there's always one unique mapping.
int index = result.indexOf(mapping);
result.set(index, mapping);
} else {
result.add(mapping);
}
} else
if (interceptorCfgObj instanceof InterceptorStackConfig) { // interceptor-ref param refer to an interceptor stack
// If its an interceptor-stack, we call this method recursively untill,
// all the params (eg. interceptorStack1.interceptor1.param etc.)
// are resolved down to a specific interceptor.
InterceptorStackConfig stackCfg = (InterceptorStackConfig) interceptorCfgObj;
List<InterceptorMapping> tmpResult = constructParameterizedInterceptorReferences(interceptorLocator, stackCfg, map, objectFactory);
for (InterceptorMapping tmpInterceptorMapping : tmpResult) {
if (result.contains(tmpInterceptorMapping)) {
int index = result.indexOf(tmpInterceptorMapping);
result.set(index, tmpInterceptorMapping);
} else {
result.add(tmpInterceptorMapping);
}
}
}
}
return result;
}
}