You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2011/12/02 17:33:45 UTC
svn commit: r1209569 [17/50] - in /struts/struts2/branches/STRUTS_3_X:
apps/blank/src/main/java/example/ apps/blank/src/test/java/example/
apps/jboss-blank/src/main/java/example/
apps/jboss-blank/src/test/java/example/ apps/mailreader/src/main/java/mai...
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/impl/NamespaceMatcher.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/impl/NamespaceMatcher.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/impl/NamespaceMatcher.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/impl/NamespaceMatcher.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,51 @@
+/*
+ * 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 org.apache.struts2.xwork2.config.impl;
+
+import org.apache.struts2.xwork2.util.PatternMatcher;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Matches namespace strings against a wildcard pattern matcher
+ *
+ * @Since 2.1
+ */
+public class NamespaceMatcher extends AbstractMatcher<NamespaceMatch> {
+ public NamespaceMatcher(PatternMatcher<?> patternMatcher,
+ Set<String> namespaces) {
+ super(patternMatcher);
+ for (String name : namespaces) {
+ if (!patternMatcher.isLiteral(name)) {
+ addPattern(name, new NamespaceMatch(name, null), false);
+ }
+ }
+ }
+
+ @Override
+ protected NamespaceMatch convert(String path, NamespaceMatch orig, Map<String, String> vars) {
+ /*Map<String,String> origVars = (Map<String,String>)vars;
+ Map<String,String> map = new HashMap<String,String>();
+ for (Map.Entry<String,String> entry : origVars.entrySet()) {
+ if (entry.getKey().length() == 1) {
+ map.put("ns"+entry.getKey(), entry.getValue());
+ }
+ }
+ */
+ return new NamespaceMatch(orig.getPattern(), vars);
+ }
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/impl/package.html
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/impl/package.html?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/impl/package.html (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/impl/package.html Fri Dec 2 16:33:03 2011
@@ -0,0 +1 @@
+<body>Configuration implementation classes.</body>
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/package.html
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/package.html?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/package.html (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/package.html Fri Dec 2 16:33:03 2011
@@ -0,0 +1 @@
+<body>Configuration core classes.</body>
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/providers/InterceptorBuilder.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/providers/InterceptorBuilder.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/providers/InterceptorBuilder.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/providers/InterceptorBuilder.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,219 @@
+/*
+ * 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 org.apache.struts2.xwork2.config.providers;
+
+import org.apache.struts2.xwork2.ObjectFactory;
+import org.apache.struts2.xwork2.config.ConfigurationException;
+import org.apache.struts2.xwork2.config.entities.InterceptorConfig;
+import org.apache.struts2.xwork2.config.entities.InterceptorLocator;
+import org.apache.struts2.xwork2.config.entities.InterceptorMapping;
+import org.apache.struts2.xwork2.config.entities.InterceptorStackConfig;
+import org.apache.struts2.xwork2.interceptor.Interceptor;
+import org.apache.struts2.xwork2.util.location.Location;
+import org.apache.struts2.xwork2.util.logging.Logger;
+import org.apache.struts2.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: 2011-12-02 12:24:48 +0100 (Fri, 02 Dec 2011) $ $Id: InterceptorBuilder.java 1209415 2011-12-02 11:24:48Z lukaszlenart $
+ */
+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 " + config.getClassName() + " at " +
+ ex.getLocation() + " probably due to a missing jar, which might " +
+ "be fine if you never plan to use the " + config.getName() + " interceptor");
+ }
+ 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 = " + 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;
+ }
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/providers/XWorkConfigurationProvider.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/providers/XWorkConfigurationProvider.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/providers/XWorkConfigurationProvider.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/providers/XWorkConfigurationProvider.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,121 @@
+package org.apache.struts2.xwork2.config.providers;
+
+import org.apache.struts2.xwork2.ActionProxyFactory;
+import org.apache.struts2.xwork2.DefaultActionProxyFactory;
+import org.apache.struts2.xwork2.DefaultTextProvider;
+import org.apache.struts2.xwork2.DefaultUnknownHandlerManager;
+import org.apache.struts2.xwork2.ObjectFactory;
+import org.apache.struts2.xwork2.TextProvider;
+import org.apache.struts2.xwork2.TextProviderSupport;
+import org.apache.struts2.xwork2.UnknownHandlerManager;
+import org.apache.struts2.xwork2.config.Configuration;
+import org.apache.struts2.xwork2.config.ConfigurationException;
+import org.apache.struts2.xwork2.config.ConfigurationProvider;
+import org.apache.struts2.xwork2.conversion.NullHandler;
+import org.apache.struts2.xwork2.conversion.ObjectTypeDeterminer;
+import org.apache.struts2.xwork2.conversion.impl.DefaultObjectTypeDeterminer;
+import org.apache.struts2.xwork2.conversion.impl.InstantiatingNullHandler;
+import org.apache.struts2.xwork2.conversion.impl.XWorkBasicConverter;
+import org.apache.struts2.xwork2.conversion.impl.XWorkConverter;
+import org.apache.struts2.xwork2.inject.ContainerBuilder;
+import org.apache.struts2.xwork2.inject.Scope;
+import org.apache.struts2.xwork2.ognl.ObjectProxy;
+import org.apache.struts2.xwork2.ognl.OgnlReflectionContextFactory;
+import org.apache.struts2.xwork2.ognl.OgnlReflectionProvider;
+import org.apache.struts2.xwork2.ognl.OgnlUtil;
+import org.apache.struts2.xwork2.ognl.OgnlValueStackFactory;
+import org.apache.struts2.xwork2.ognl.accessor.CompoundRootAccessor;
+import org.apache.struts2.xwork2.ognl.accessor.ObjectAccessor;
+import org.apache.struts2.xwork2.ognl.accessor.ObjectProxyPropertyAccessor;
+import org.apache.struts2.xwork2.ognl.accessor.XWorkCollectionPropertyAccessor;
+import org.apache.struts2.xwork2.ognl.accessor.XWorkEnumerationAccessor;
+import org.apache.struts2.xwork2.ognl.accessor.XWorkIteratorPropertyAccessor;
+import org.apache.struts2.xwork2.ognl.accessor.XWorkListPropertyAccessor;
+import org.apache.struts2.xwork2.ognl.accessor.XWorkMapPropertyAccessor;
+import org.apache.struts2.xwork2.ognl.accessor.XWorkMethodAccessor;
+import org.apache.struts2.xwork2.util.CompoundRoot;
+import org.apache.struts2.xwork2.util.PatternMatcher;
+import org.apache.struts2.xwork2.util.ValueStackFactory;
+import org.apache.struts2.xwork2.util.WildcardHelper;
+import org.apache.struts2.xwork2.util.location.LocatableProperties;
+import org.apache.struts2.xwork2.util.reflection.ReflectionContextFactory;
+import org.apache.struts2.xwork2.util.reflection.ReflectionProvider;
+import org.apache.struts2.xwork2.validator.ActionValidatorManager;
+import org.apache.struts2.xwork2.validator.AnnotationActionValidatorManager;
+import org.apache.struts2.xwork2.validator.DefaultActionValidatorManager;
+import org.apache.struts2.xwork2.validator.DefaultValidatorFactory;
+import org.apache.struts2.xwork2.validator.DefaultValidatorFileParser;
+import org.apache.struts2.xwork2.validator.ValidatorFactory;
+import org.apache.struts2.xwork2.validator.ValidatorFileParser;
+import ognl.MethodAccessor;
+import ognl.PropertyAccessor;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class XWorkConfigurationProvider implements ConfigurationProvider {
+
+ public void destroy() {
+ }
+
+ public void init(Configuration configuration) throws ConfigurationException {
+ }
+
+ public void loadPackages() throws ConfigurationException {
+ }
+
+ public boolean needsReload() {
+ return false;
+ }
+
+ public void register(ContainerBuilder builder, LocatableProperties props)
+ throws ConfigurationException {
+
+ builder.factory(ObjectFactory.class)
+ .factory(ActionProxyFactory.class, DefaultActionProxyFactory.class, Scope.SINGLETON)
+ .factory(ObjectTypeDeterminer.class, DefaultObjectTypeDeterminer.class, Scope.SINGLETON)
+ .factory(XWorkConverter.class, Scope.SINGLETON)
+ .factory(ValueStackFactory.class, OgnlValueStackFactory.class, Scope.SINGLETON)
+ .factory(ValidatorFactory.class, DefaultValidatorFactory.class, Scope.SINGLETON)
+ .factory(ValidatorFileParser.class, DefaultValidatorFileParser.class, Scope.SINGLETON)
+ .factory(PatternMatcher.class, WildcardHelper.class, Scope.SINGLETON)
+ .factory(ReflectionProvider.class, OgnlReflectionProvider.class, Scope.SINGLETON)
+ .factory(ReflectionContextFactory.class, OgnlReflectionContextFactory.class, Scope.SINGLETON)
+ .factory(PropertyAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON)
+ .factory(PropertyAccessor.class, Object.class.getName(), ObjectAccessor.class, Scope.SINGLETON)
+ .factory(PropertyAccessor.class, Iterator.class.getName(), XWorkIteratorPropertyAccessor.class, Scope.SINGLETON)
+ .factory(PropertyAccessor.class, Enumeration.class.getName(), XWorkEnumerationAccessor.class, Scope.SINGLETON)
+ .factory(UnknownHandlerManager.class, DefaultUnknownHandlerManager.class, Scope.SINGLETON)
+
+ // silly workarounds for ognl since there is no way to flush its caches
+ .factory(PropertyAccessor.class, List.class.getName(), XWorkListPropertyAccessor.class, Scope.SINGLETON)
+ .factory(PropertyAccessor.class, ArrayList.class.getName(), XWorkListPropertyAccessor.class, Scope.SINGLETON)
+ .factory(PropertyAccessor.class, HashSet.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON)
+ .factory(PropertyAccessor.class, Set.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON)
+ .factory(PropertyAccessor.class, HashMap.class.getName(), XWorkMapPropertyAccessor.class, Scope.SINGLETON)
+ .factory(PropertyAccessor.class, Map.class.getName(), XWorkMapPropertyAccessor.class, Scope.SINGLETON)
+
+ .factory(PropertyAccessor.class, Collection.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON)
+ .factory(PropertyAccessor.class, ObjectProxy.class.getName(), ObjectProxyPropertyAccessor.class, Scope.SINGLETON)
+ .factory(MethodAccessor.class, Object.class.getName(), XWorkMethodAccessor.class, Scope.SINGLETON)
+ .factory(MethodAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON)
+ .factory(NullHandler.class, Object.class.getName(), InstantiatingNullHandler.class, Scope.SINGLETON)
+ .factory(ActionValidatorManager.class, AnnotationActionValidatorManager.class, Scope.SINGLETON)
+ .factory(ActionValidatorManager.class, "no-annotations", DefaultActionValidatorManager.class, Scope.SINGLETON)
+ .factory(TextProvider.class, "system", DefaultTextProvider.class, Scope.SINGLETON)
+ .factory(TextProvider.class, TextProviderSupport.class, Scope.SINGLETON)
+ .factory(OgnlUtil.class, Scope.SINGLETON)
+ .factory(XWorkBasicConverter.class, Scope.SINGLETON);
+ props.setProperty("devMode", Boolean.FALSE.toString());
+ props.setProperty("logMissingProperties", Boolean.FALSE.toString());
+ props.setProperty("enableOGNLExpressionCache", Boolean.TRUE.toString());
+ }
+
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/providers/XmlConfigurationProvider.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/providers/XmlConfigurationProvider.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/providers/XmlConfigurationProvider.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/providers/XmlConfigurationProvider.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,1052 @@
+/*
+ * 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 org.apache.struts2.xwork2.config.providers;
+
+import org.apache.struts2.xwork2.Action;
+import org.apache.struts2.xwork2.ObjectFactory;
+import org.apache.struts2.xwork2.XWorkException;
+import org.apache.struts2.xwork2.config.Configuration;
+import org.apache.struts2.xwork2.config.ConfigurationException;
+import org.apache.struts2.xwork2.config.ConfigurationProvider;
+import org.apache.struts2.xwork2.config.ConfigurationUtil;
+import org.apache.struts2.xwork2.config.entities.ExceptionMappingConfig;
+import org.apache.struts2.xwork2.config.entities.InterceptorStackConfig;
+import org.apache.struts2.xwork2.config.entities.UnknownHandlerConfig;
+import org.apache.struts2.xwork2.config.impl.LocatableFactory;
+import org.apache.struts2.xwork2.inject.Container;
+import org.apache.struts2.xwork2.inject.ContainerBuilder;
+import org.apache.struts2.xwork2.inject.Inject;
+import org.apache.struts2.xwork2.inject.Scope;
+import org.apache.struts2.xwork2.util.ClassLoaderUtil;
+import org.apache.struts2.xwork2.util.location.LocatableProperties;
+import org.apache.struts2.xwork2.util.location.Location;
+import org.apache.struts2.xwork2.util.location.LocationUtils;
+import org.apache.struts2.xwork2.util.logging.Logger;
+import org.apache.struts2.xwork2.util.logging.LoggerFactory;
+import org.apache.struts2.xwork2.config.entities.ActionConfig;
+import org.apache.struts2.xwork2.config.entities.InterceptorConfig;
+import org.apache.struts2.xwork2.config.entities.InterceptorMapping;
+import org.apache.struts2.xwork2.config.entities.PackageConfig;
+import org.apache.struts2.xwork2.config.entities.ResultConfig;
+import org.apache.struts2.xwork2.config.entities.ResultTypeConfig;
+import org.apache.struts2.xwork2.util.ClassPathFinder;
+import org.apache.struts2.xwork2.util.DomHelper;
+import org.apache.struts2.xwork2.util.FileManager;
+import org.apache.struts2.xwork2.util.TextParseUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.apache.commons.lang.StringUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Modifier;
+import java.net.URL;
+import java.util.*;
+
+
+/**
+ * Looks in the classpath for an XML file, "xwork.xml" by default,
+ * and uses it for the XWork configuration.
+ *
+ * @author tmjee
+ * @author Rainer Hermanns
+ * @author Neo
+ * @version $Revision: 1209415 $
+ */
+public class XmlConfigurationProvider implements ConfigurationProvider {
+
+ private static final Logger LOG = LoggerFactory.getLogger(XmlConfigurationProvider.class);
+
+ private List<Document> documents;
+ private Set<String> includedFileNames;
+ private String configFileName;
+ private ObjectFactory objectFactory;
+
+ private Set<String> loadedFileUrls = new HashSet<String>();
+ private boolean errorIfMissing;
+ private Map<String, String> dtdMappings;
+ private Configuration configuration;
+ private boolean throwExceptionOnDuplicateBeans = true;
+
+ public XmlConfigurationProvider() {
+ this("xwork.xml", true);
+ }
+
+ public XmlConfigurationProvider(String filename) {
+ this(filename, true);
+ }
+
+ public XmlConfigurationProvider(String filename, boolean errorIfMissing) {
+ this.configFileName = filename;
+ this.errorIfMissing = errorIfMissing;
+
+ Map<String, String> mappings = new HashMap<String, String>();
+ mappings.put("-//Apache Struts//XWork 2.3//EN", "xwork-2.3.dtd");
+ mappings.put("-//Apache Struts//XWork 2.1.3//EN", "xwork-2.1.3.dtd");
+ mappings.put("-//Apache Struts//XWork 2.1//EN", "xwork-2.1.dtd");
+ mappings.put("-//Apache Struts//XWork 2.0//EN", "xwork-2.0.dtd");
+ mappings.put("-//Apache Struts//XWork 1.1.1//EN", "xwork-1.1.1.dtd");
+ mappings.put("-//Apache Struts//XWork 1.1//EN", "xwork-1.1.dtd");
+ mappings.put("-//Apache Struts//XWork 1.0//EN", "xwork-1.0.dtd");
+ setDtdMappings(mappings);
+ }
+
+ public void setThrowExceptionOnDuplicateBeans(boolean val) {
+ this.throwExceptionOnDuplicateBeans = val;
+ }
+
+ public void setDtdMappings(Map<String, String> mappings) {
+ this.dtdMappings = Collections.unmodifiableMap(mappings);
+ }
+
+ @Inject
+ public void setObjectFactory(ObjectFactory objectFactory) {
+ this.objectFactory = objectFactory;
+ }
+
+ /**
+ * Returns an unmodifiable map of DTD mappings
+ */
+ public Map<String, String> getDtdMappings() {
+ return dtdMappings;
+ }
+
+ public void init(Configuration configuration) {
+ this.configuration = configuration;
+ this.includedFileNames = configuration.getLoadedFileNames();
+ loadDocuments(configFileName);
+ }
+
+ public void destroy() {
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof XmlConfigurationProvider)) {
+ return false;
+ }
+
+ final XmlConfigurationProvider xmlConfigurationProvider = (XmlConfigurationProvider) o;
+
+ if ((configFileName != null) ? (!configFileName.equals(xmlConfigurationProvider.configFileName)) : (xmlConfigurationProvider.configFileName != null)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return ((configFileName != null) ? configFileName.hashCode() : 0);
+ }
+
+ private void loadDocuments(String configFileName) {
+ try {
+ loadedFileUrls.clear();
+ documents = loadConfigurationFiles(configFileName, null);
+ } catch (ConfigurationException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new ConfigurationException("Error loading configuration file " + configFileName, e);
+ }
+ }
+
+ public void register(ContainerBuilder containerBuilder, LocatableProperties props) throws ConfigurationException {
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Parsing configuration file [" + configFileName + "]");
+ }
+ Map<String, Node> loadedBeans = new HashMap<String, Node>();
+ for (Document doc : documents) {
+ Element rootElement = doc.getDocumentElement();
+ NodeList children = rootElement.getChildNodes();
+ int childSize = children.getLength();
+
+ for (int i = 0; i < childSize; i++) {
+ Node childNode = children.item(i);
+
+ if (childNode instanceof Element) {
+ Element child = (Element) childNode;
+
+ final String nodeName = child.getNodeName();
+
+ if ("bean".equals(nodeName)) {
+ String type = child.getAttribute("type");
+ String name = child.getAttribute("name");
+ String impl = child.getAttribute("class");
+ String onlyStatic = child.getAttribute("static");
+ String scopeStr = child.getAttribute("scope");
+ boolean optional = "true".equals(child.getAttribute("optional"));
+ Scope scope = Scope.SINGLETON;
+ if ("default".equals(scopeStr)) {
+ scope = Scope.DEFAULT;
+ } else if ("request".equals(scopeStr)) {
+ scope = Scope.REQUEST;
+ } else if ("session".equals(scopeStr)) {
+ scope = Scope.SESSION;
+ } else if ("singleton".equals(scopeStr)) {
+ scope = Scope.SINGLETON;
+ } else if ("thread".equals(scopeStr)) {
+ scope = Scope.THREAD;
+ }
+
+ if (StringUtils.isEmpty(name)) {
+ name = Container.DEFAULT_NAME;
+ }
+
+ try {
+ Class cimpl = ClassLoaderUtil.loadClass(impl, getClass());
+ Class ctype = cimpl;
+ if (StringUtils.isNotEmpty(type)) {
+ ctype = ClassLoaderUtil.loadClass(type, getClass());
+ }
+ if ("true".equals(onlyStatic)) {
+ // Force loading of class to detect no class def found exceptions
+ cimpl.getDeclaredClasses();
+ containerBuilder.injectStatics(cimpl);
+ } else {
+ if (containerBuilder.contains(ctype, name)) {
+ Location loc = LocationUtils.getLocation(loadedBeans.get(ctype.getName() + name));
+ if (throwExceptionOnDuplicateBeans) {
+ throw new ConfigurationException("Bean type " + ctype + " with the name " +
+ name + " has already been loaded by " + loc, child);
+ }
+ }
+
+ // Force loading of class to detect no class def found exceptions
+ cimpl.getDeclaredConstructors();
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Loaded type:" + type + " name:" + name + " impl:" + impl);
+ }
+ containerBuilder.factory(ctype, name, new LocatableFactory(name, ctype, cimpl, scope, childNode), scope);
+ }
+ loadedBeans.put(ctype.getName() + name, child);
+ } catch (Throwable ex) {
+ if (!optional) {
+ throw new ConfigurationException("Unable to load bean: type:" + type + " class:" + impl, ex, childNode);
+ } else {
+ LOG.debug("Unable to load optional class: " + ex);
+ }
+ }
+ } else if ("constant".equals(nodeName)) {
+ String name = child.getAttribute("name");
+ String value = child.getAttribute("value");
+ props.setProperty(name, value, childNode);
+ } else if (nodeName.equals("unknown-handler-stack")) {
+ List<UnknownHandlerConfig> unknownHandlerStack = new ArrayList<UnknownHandlerConfig>();
+ NodeList unknownHandlers = child.getElementsByTagName("unknown-handler-ref");
+ int unknownHandlersSize = unknownHandlers.getLength();
+
+ for (int k = 0; k < unknownHandlersSize; k++) {
+ Element unknownHandler = (Element) unknownHandlers.item(k);
+ unknownHandlerStack.add(new UnknownHandlerConfig(unknownHandler.getAttribute("name")));
+ }
+
+ if (!unknownHandlerStack.isEmpty())
+ configuration.setUnknownHandlerStack(unknownHandlerStack);
+ }
+ }
+ }
+ }
+ }
+
+ public void loadPackages() throws ConfigurationException {
+ List<Element> reloads = new ArrayList<Element>();
+ for (Document doc : documents) {
+ Element rootElement = doc.getDocumentElement();
+ NodeList children = rootElement.getChildNodes();
+ int childSize = children.getLength();
+
+ for (int i = 0; i < childSize; i++) {
+ Node childNode = children.item(i);
+
+ if (childNode instanceof Element) {
+ Element child = (Element) childNode;
+
+ final String nodeName = child.getNodeName();
+
+ if ("package".equals(nodeName)) {
+ PackageConfig cfg = addPackage(child);
+ if (cfg.isNeedsRefresh()) {
+ reloads.add(child);
+ }
+ }
+ }
+ }
+ loadExtraConfiguration(doc);
+ }
+
+ if (reloads.size() > 0) {
+ reloadRequiredPackages(reloads);
+ }
+
+ for (Document doc : documents) {
+ loadExtraConfiguration(doc);
+ }
+
+ documents.clear();
+ configuration = null;
+ }
+
+ private void reloadRequiredPackages(List<Element> reloads) {
+ if (reloads.size() > 0) {
+ List<Element> result = new ArrayList<Element>();
+ for (Element pkg : reloads) {
+ PackageConfig cfg = addPackage(pkg);
+ if (cfg.isNeedsRefresh()) {
+ result.add(pkg);
+ }
+ }
+ if ((result.size() > 0) && (result.size() != reloads.size())) {
+ reloadRequiredPackages(result);
+ return;
+ }
+
+ // Print out error messages for all misconfigured inheritence packages
+ if (result.size() > 0) {
+ for (Element rp : result) {
+ String parent = rp.getAttribute("extends");
+ if (parent != null) {
+ List<PackageConfig> parents = ConfigurationUtil.buildParentsFromString(configuration, parent);
+ if (parents != null && parents.size() <= 0) {
+ LOG.error("Unable to find parent packages " + parent);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Tells whether the ConfigurationProvider should reload its configuration. This method should only be called
+ * if ConfigurationManager.isReloadingConfigs() is true.
+ *
+ * @return true if the file has been changed since the last time we read it
+ */
+ public boolean needsReload() {
+
+ for (String url : loadedFileUrls) {
+ if (FileManager.fileNeedsReloading(url)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected void addAction(Element actionElement, PackageConfig.Builder packageContext) throws ConfigurationException {
+ String name = actionElement.getAttribute("name");
+ String className = actionElement.getAttribute("class");
+ String methodName = actionElement.getAttribute("method");
+ Location location = DomHelper.getLocationObject(actionElement);
+
+ if (location == null) {
+ if (LOG.isWarnEnabled()) {
+ LOG.warn("location null for " + className);
+ }
+ }
+ //methodName should be null if it's not set
+ methodName = (methodName.trim().length() > 0) ? methodName.trim() : null;
+
+ // if there isnt a class name specified for an <action/> then try to
+ // use the default-class-ref from the <package/>
+ if (StringUtils.isEmpty(className)) {
+ // if there is a package default-class-ref use that, otherwise use action support
+ /* if (StringUtils.isNotEmpty(packageContext.getDefaultClassRef())) {
+ className = packageContext.getDefaultClassRef();
+ } else {
+ className = ActionSupport.class.getName();
+ }*/
+
+ } else {
+ if (!verifyAction(className, name, location)) {
+ if (LOG.isErrorEnabled())
+ LOG.error("Unable to verify action [#0] with class [#1], from [#2]", name, className, location.toString());
+ return;
+ }
+ }
+
+ Map<String, ResultConfig> results;
+ try {
+ results = buildResults(actionElement, packageContext);
+ } catch (ConfigurationException e) {
+ throw new ConfigurationException("Error building results for action " + name + " in namespace " + packageContext.getNamespace(), e, actionElement);
+ }
+
+ List<InterceptorMapping> interceptorList = buildInterceptorList(actionElement, packageContext);
+
+ List<ExceptionMappingConfig> exceptionMappings = buildExceptionMappings(actionElement, packageContext);
+
+ Set<String> allowedMethods = buildAllowedMethods(actionElement, packageContext);
+
+ ActionConfig actionConfig = new ActionConfig.Builder(packageContext.getName(), name, className)
+ .methodName(methodName)
+ .addResultConfigs(results)
+ .addInterceptors(interceptorList)
+ .addExceptionMappings(exceptionMappings)
+ .addParams(XmlHelper.getParams(actionElement))
+ .addAllowedMethod(allowedMethods)
+ .location(location)
+ .build();
+ packageContext.addActionConfig(name, actionConfig);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Loaded " + (StringUtils.isNotEmpty(packageContext.getNamespace()) ? (packageContext.getNamespace() + "/") : "") + name + " in '" + packageContext.getName() + "' package:" + actionConfig);
+ }
+ }
+
+ protected boolean verifyAction(String className, String name, Location loc) {
+ if (className.indexOf('{') > -1) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Action class [" + className + "] contains a wildcard " +
+ "replacement value, so it can't be verified");
+ }
+ return true;
+ }
+ try {
+ if (objectFactory.isNoArgConstructorRequired()) {
+ Class clazz = objectFactory.getClassInstance(className);
+ if (!Modifier.isPublic(clazz.getModifiers())) {
+ throw new ConfigurationException("Action class [" + className + "] is not public", loc);
+ }
+ clazz.getConstructor(new Class[]{});
+ }
+ } catch (ClassNotFoundException e) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Class not found for action [" + className + "]", e);
+ }
+ throw new ConfigurationException("Action class [" + className + "] not found", loc);
+ } catch (NoSuchMethodException e) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("No constructor found for action [" + className + "]", e);
+ }
+ throw new ConfigurationException("Action class [" + className + "] does not have a public no-arg constructor", e, loc);
+ } catch (RuntimeException ex) {
+ // Probably not a big deal, like request or session-scoped Spring 2 beans that need a real request
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Unable to verify action class [" + className + "] exists at initialization");
+ }
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Action verification cause", ex);
+ }
+ } catch (Exception ex) {
+ // Default to failing fast
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Unable to verify action class [" + className + "]", ex);
+ }
+ throw new ConfigurationException(ex, loc);
+ }
+ return true;
+ }
+
+ /**
+ * Create a PackageConfig from an XML element representing it.
+ */
+ protected PackageConfig addPackage(Element packageElement) throws ConfigurationException {
+ PackageConfig.Builder newPackage = buildPackageContext(packageElement);
+
+ if (newPackage.isNeedsRefresh()) {
+ return newPackage.build();
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Loaded " + newPackage);
+ }
+
+ // add result types (and default result) to this package
+ addResultTypes(newPackage, packageElement);
+
+ // load the interceptors and interceptor stacks for this package
+ loadInterceptors(newPackage, packageElement);
+
+ // load the default interceptor reference for this package
+ loadDefaultInterceptorRef(newPackage, packageElement);
+
+ // load the default class ref for this package
+ loadDefaultClassRef(newPackage, packageElement);
+
+ // load the global result list for this package
+ loadGlobalResults(newPackage, packageElement);
+
+ // load the global exception handler list for this package
+ loadGobalExceptionMappings(newPackage, packageElement);
+
+ // get actions
+ NodeList actionList = packageElement.getElementsByTagName("action");
+
+ for (int i = 0; i < actionList.getLength(); i++) {
+ Element actionElement = (Element) actionList.item(i);
+ addAction(actionElement, newPackage);
+ }
+
+ // load the default action reference for this package
+ loadDefaultActionRef(newPackage, packageElement);
+
+ PackageConfig cfg = newPackage.build();
+ configuration.addPackageConfig(cfg.getName(), cfg);
+ return cfg;
+ }
+
+ protected void addResultTypes(PackageConfig.Builder packageContext, Element element) {
+ NodeList resultTypeList = element.getElementsByTagName("result-type");
+
+ for (int i = 0; i < resultTypeList.getLength(); i++) {
+ Element resultTypeElement = (Element) resultTypeList.item(i);
+ String name = resultTypeElement.getAttribute("name");
+ String className = resultTypeElement.getAttribute("class");
+ String def = resultTypeElement.getAttribute("default");
+
+ Location loc = DomHelper.getLocationObject(resultTypeElement);
+
+ Class clazz = verifyResultType(className, loc);
+ if (clazz != null) {
+ String paramName = null;
+ try {
+ paramName = (String) clazz.getField("DEFAULT_PARAM").get(null);
+ }
+ catch (Throwable t) {
+ // if we get here, the result type doesn't have a default param defined.
+ }
+ ResultTypeConfig.Builder resultType = new ResultTypeConfig.Builder(name, className).defaultResultParam(paramName)
+ .location(DomHelper.getLocationObject(resultTypeElement));
+
+ Map<String, String> params = XmlHelper.getParams(resultTypeElement);
+
+ if (!params.isEmpty()) {
+ resultType.addParams(params);
+ }
+ packageContext.addResultTypeConfig(resultType.build());
+
+ // set the default result type
+ if ("true".equals(def)) {
+ packageContext.defaultResultType(name);
+ }
+ }
+ }
+ }
+
+ protected Class verifyResultType(String className, Location loc) {
+ try {
+ return objectFactory.getClassInstance(className);
+ } catch (ClassNotFoundException e) {
+ if (LOG.isWarnEnabled()) {
+ LOG.warn("Result class [" + className + "] doesn't exist (ClassNotFoundException) at " +
+ loc.toString() + ", ignoring", e);
+ }
+ } catch (NoClassDefFoundError e) {
+ if (LOG.isWarnEnabled()) {
+ LOG.warn("Result class [" + className + "] doesn't exist (NoClassDefFoundError) at " +
+ loc.toString() + ", ignoring", e);
+ }
+ }
+
+ return null;
+ }
+
+ protected List<InterceptorMapping> buildInterceptorList(Element element, PackageConfig.Builder context) throws ConfigurationException {
+ List<InterceptorMapping> interceptorList = new ArrayList<InterceptorMapping>();
+ NodeList interceptorRefList = element.getElementsByTagName("interceptor-ref");
+
+ for (int i = 0; i < interceptorRefList.getLength(); i++) {
+ Element interceptorRefElement = (Element) interceptorRefList.item(i);
+
+ if (interceptorRefElement.getParentNode().equals(element) || interceptorRefElement.getParentNode().getNodeName().equals(element.getNodeName())) {
+ List<InterceptorMapping> interceptors = lookupInterceptorReference(context, interceptorRefElement);
+ interceptorList.addAll(interceptors);
+ }
+ }
+
+ return interceptorList;
+ }
+
+ /**
+ * This method builds a package context by looking for the parents of this new package.
+ * <p/>
+ * If no parents are found, it will return a root package.
+ */
+ protected PackageConfig.Builder buildPackageContext(Element packageElement) {
+ String parent = packageElement.getAttribute("extends");
+ String abstractVal = packageElement.getAttribute("abstract");
+ boolean isAbstract = Boolean.parseBoolean(abstractVal);
+ String name = StringUtils.defaultString(packageElement.getAttribute("name"));
+ String namespace = StringUtils.defaultString(packageElement.getAttribute("namespace"));
+ String strictDMIVal = StringUtils.defaultString(packageElement.getAttribute("strict-method-invocation"));
+ boolean strictDMI = Boolean.parseBoolean(strictDMIVal);
+
+ if (StringUtils.isNotEmpty(packageElement.getAttribute("externalReferenceResolver"))) {
+ throw new ConfigurationException("The 'externalReferenceResolver' attribute has been removed. Please use " +
+ "a custom ObjectFactory or Interceptor.", packageElement);
+ }
+
+ PackageConfig.Builder cfg = new PackageConfig.Builder(name)
+ .namespace(namespace)
+ .isAbstract(isAbstract)
+ .strictMethodInvocation(strictDMI)
+ .location(DomHelper.getLocationObject(packageElement));
+
+ if (StringUtils.isNotEmpty(StringUtils.defaultString(parent))) { // has parents, let's look it up
+
+ List<PackageConfig> parents = ConfigurationUtil.buildParentsFromString(configuration, parent);
+
+ if (parents.size() <= 0) {
+ cfg.needsRefresh(true);
+ } else {
+ cfg.addParents(parents);
+ }
+ }
+
+ return cfg;
+ }
+
+ /**
+ * Build a map of ResultConfig objects from below a given XML element.
+ */
+ protected Map<String, ResultConfig> buildResults(Element element, PackageConfig.Builder packageContext) {
+ NodeList resultEls = element.getElementsByTagName("result");
+
+ Map<String, ResultConfig> results = new LinkedHashMap<String, ResultConfig>();
+
+ for (int i = 0; i < resultEls.getLength(); i++) {
+ Element resultElement = (Element) resultEls.item(i);
+
+ if (resultElement.getParentNode().equals(element) || resultElement.getParentNode().getNodeName().equals(element.getNodeName())) {
+ String resultName = resultElement.getAttribute("name");
+ String resultType = resultElement.getAttribute("type");
+
+ // if you don't specify a name on <result/>, it defaults to "success"
+ if (StringUtils.isEmpty(resultName)) {
+ resultName = Action.SUCCESS;
+ }
+
+ // there is no result type, so let's inherit from the parent package
+ if (StringUtils.isEmpty(resultType)) {
+ resultType = packageContext.getFullDefaultResultType();
+
+ // now check if there is a result type now
+ if (StringUtils.isEmpty(resultType)) {
+ // uh-oh, we have a problem
+ throw new ConfigurationException("No result type specified for result named '"
+ + resultName + "', perhaps the parent package does not specify the result type?", resultElement);
+ }
+ }
+
+
+ ResultTypeConfig config = packageContext.getResultType(resultType);
+
+ if (config == null) {
+ throw new ConfigurationException("There is no result type defined for type '" + resultType
+ + "' mapped with name '" + resultName + "'."
+ + " Did you mean '" + guessResultType(resultType) + "'?", resultElement);
+ }
+
+ String resultClass = config.getClazz();
+
+ // invalid result type specified in result definition
+ if (resultClass == null) {
+ throw new ConfigurationException("Result type '" + resultType + "' is invalid");
+ }
+
+ Map<String, String> resultParams = XmlHelper.getParams(resultElement);
+
+ if (resultParams.size() == 0) // maybe we just have a body - therefore a default parameter
+ {
+ // if <result ...>something</result> then we add a parameter of 'something' as this is the most used result param
+ if (resultElement.getChildNodes().getLength() >= 1) {
+ resultParams = new LinkedHashMap<String, String>();
+
+ String paramName = config.getDefaultResultParam();
+ if (paramName != null) {
+ StringBuilder paramValue = new StringBuilder();
+ for (int j = 0; j < resultElement.getChildNodes().getLength(); j++) {
+ if (resultElement.getChildNodes().item(j).getNodeType() == Node.TEXT_NODE) {
+ String val = resultElement.getChildNodes().item(j).getNodeValue();
+ if (val != null) {
+ paramValue.append(val);
+ }
+ }
+ }
+ String val = paramValue.toString().trim();
+ if (val.length() > 0) {
+ resultParams.put(paramName, val);
+ }
+ } else {
+ if (LOG.isWarnEnabled()) {
+ LOG.warn("no default parameter defined for result of type " + config.getName());
+ }
+ }
+ }
+ }
+
+ // create new param map, so that the result param can override the config param
+ Map<String, String> params = new LinkedHashMap<String, String>();
+ Map<String, String> configParams = config.getParams();
+ if (configParams != null) {
+ params.putAll(configParams);
+ }
+ params.putAll(resultParams);
+
+ ResultConfig resultConfig = new ResultConfig.Builder(resultName, resultClass)
+ .addParams(params)
+ .location(DomHelper.getLocationObject(element))
+ .build();
+ results.put(resultConfig.getName(), resultConfig);
+ }
+ }
+
+ return results;
+ }
+
+ protected String guessResultType(String type) {
+ StringBuilder sb = null;
+ if (type != null) {
+ sb = new StringBuilder();
+ boolean capNext = false;
+ for (int x=0; x<type.length(); x++) {
+ char c = type.charAt(x);
+ if (c == '-') {
+ capNext = true;
+ continue;
+ } else if (Character.isLowerCase(c) && capNext) {
+ c = Character.toUpperCase(c);
+ capNext = false;
+ }
+ sb.append(c);
+ }
+ }
+ return (sb != null ? sb.toString() : null);
+ }
+
+ /**
+ * Build a map of ResultConfig objects from below a given XML element.
+ */
+ protected List<ExceptionMappingConfig> buildExceptionMappings(Element element, PackageConfig.Builder packageContext) {
+ NodeList exceptionMappingEls = element.getElementsByTagName("exception-mapping");
+
+ List<ExceptionMappingConfig> exceptionMappings = new ArrayList<ExceptionMappingConfig>();
+
+ for (int i = 0; i < exceptionMappingEls.getLength(); i++) {
+ Element ehElement = (Element) exceptionMappingEls.item(i);
+
+ if (ehElement.getParentNode().equals(element) || ehElement.getParentNode().getNodeName().equals(element.getNodeName())) {
+ String emName = ehElement.getAttribute("name");
+ String exceptionClassName = ehElement.getAttribute("exception");
+ String exceptionResult = ehElement.getAttribute("result");
+
+ Map<String, String> params = XmlHelper.getParams(ehElement);
+
+ if (StringUtils.isEmpty(emName)) {
+ emName = exceptionResult;
+ }
+
+ ExceptionMappingConfig ehConfig = new ExceptionMappingConfig.Builder(emName, exceptionClassName, exceptionResult)
+ .addParams(params)
+ .location(DomHelper.getLocationObject(ehElement))
+ .build();
+ exceptionMappings.add(ehConfig);
+ }
+ }
+
+ return exceptionMappings;
+ }
+
+ protected Set<String> buildAllowedMethods(Element element, PackageConfig.Builder packageContext) {
+ NodeList allowedMethodsEls = element.getElementsByTagName("allowed-methods");
+
+ Set<String> allowedMethods = null;
+
+ if (allowedMethodsEls.getLength() > 0) {
+ allowedMethods = new HashSet<String>();
+ Node n = allowedMethodsEls.item(0).getFirstChild();
+ if (n != null) {
+ String s = n.getNodeValue().trim();
+ if (s.length() > 0) {
+ allowedMethods = TextParseUtil.commaDelimitedStringToSet(s);
+ }
+ }
+ } else if (packageContext.isStrictMethodInvocation()) {
+ allowedMethods = new HashSet<String>();
+ }
+
+ return allowedMethods;
+ }
+
+ protected void loadDefaultInterceptorRef(PackageConfig.Builder packageContext, Element element) {
+ NodeList resultTypeList = element.getElementsByTagName("default-interceptor-ref");
+
+ if (resultTypeList.getLength() > 0) {
+ Element defaultRefElement = (Element) resultTypeList.item(0);
+ packageContext.defaultInterceptorRef(defaultRefElement.getAttribute("name"));
+ }
+ }
+
+ protected void loadDefaultActionRef(PackageConfig.Builder packageContext, Element element) {
+ NodeList resultTypeList = element.getElementsByTagName("default-action-ref");
+
+ if (resultTypeList.getLength() > 0) {
+ Element defaultRefElement = (Element) resultTypeList.item(0);
+ packageContext.defaultActionRef(defaultRefElement.getAttribute("name"));
+ }
+ }
+
+ /**
+ * Load all of the global results for this package from the XML element.
+ */
+ protected void loadGlobalResults(PackageConfig.Builder packageContext, Element packageElement) {
+ NodeList globalResultList = packageElement.getElementsByTagName("global-results");
+
+ if (globalResultList.getLength() > 0) {
+ Element globalResultElement = (Element) globalResultList.item(0);
+ Map<String, ResultConfig> results = buildResults(globalResultElement, packageContext);
+ packageContext.addGlobalResultConfigs(results);
+ }
+ }
+
+ protected void loadDefaultClassRef(PackageConfig.Builder packageContext, Element element) {
+ NodeList defaultClassRefList = element.getElementsByTagName("default-class-ref");
+ if (defaultClassRefList.getLength() > 0) {
+ Element defaultClassRefElement = (Element) defaultClassRefList.item(0);
+ packageContext.defaultClassRef(defaultClassRefElement.getAttribute("class"));
+ }
+ }
+
+ /**
+ * Load all of the global results for this package from the XML element.
+ */
+ protected void loadGobalExceptionMappings(PackageConfig.Builder packageContext, Element packageElement) {
+ NodeList globalExceptionMappingList = packageElement.getElementsByTagName("global-exception-mappings");
+
+ if (globalExceptionMappingList.getLength() > 0) {
+ Element globalExceptionMappingElement = (Element) globalExceptionMappingList.item(0);
+ List<ExceptionMappingConfig> exceptionMappings = buildExceptionMappings(globalExceptionMappingElement, packageContext);
+ packageContext.addGlobalExceptionMappingConfigs(exceptionMappings);
+ }
+ }
+
+ // protected void loadIncludes(Element rootElement, DocumentBuilder db) throws Exception {
+ // NodeList includeList = rootElement.getElementsByTagName("include");
+ //
+ // for (int i = 0; i < includeList.getLength(); i++) {
+ // Element includeElement = (Element) includeList.item(i);
+ // String fileName = includeElement.getAttribute("file");
+ // includedFileNames.add(fileName);
+ // loadConfigurationFile(fileName, db);
+ // }
+ // }
+ protected InterceptorStackConfig loadInterceptorStack(Element element, PackageConfig.Builder context) throws ConfigurationException {
+ String name = element.getAttribute("name");
+
+ InterceptorStackConfig.Builder config = new InterceptorStackConfig.Builder(name)
+ .location(DomHelper.getLocationObject(element));
+ NodeList interceptorRefList = element.getElementsByTagName("interceptor-ref");
+
+ for (int j = 0; j < interceptorRefList.getLength(); j++) {
+ Element interceptorRefElement = (Element) interceptorRefList.item(j);
+ List<InterceptorMapping> interceptors = lookupInterceptorReference(context, interceptorRefElement);
+ config.addInterceptors(interceptors);
+ }
+
+ return config.build();
+ }
+
+ protected void loadInterceptorStacks(Element element, PackageConfig.Builder context) throws ConfigurationException {
+ NodeList interceptorStackList = element.getElementsByTagName("interceptor-stack");
+
+ for (int i = 0; i < interceptorStackList.getLength(); i++) {
+ Element interceptorStackElement = (Element) interceptorStackList.item(i);
+
+ InterceptorStackConfig config = loadInterceptorStack(interceptorStackElement, context);
+
+ context.addInterceptorStackConfig(config);
+ }
+ }
+
+ protected void loadInterceptors(PackageConfig.Builder context, Element element) throws ConfigurationException {
+ NodeList interceptorList = element.getElementsByTagName("interceptor");
+
+ for (int i = 0; i < interceptorList.getLength(); i++) {
+ Element interceptorElement = (Element) interceptorList.item(i);
+ String name = interceptorElement.getAttribute("name");
+ String className = interceptorElement.getAttribute("class");
+
+ Map<String, String> params = XmlHelper.getParams(interceptorElement);
+ InterceptorConfig config = new InterceptorConfig.Builder(name, className)
+ .addParams(params)
+ .location(DomHelper.getLocationObject(interceptorElement))
+ .build();
+
+ context.addInterceptorConfig(config);
+ }
+
+ loadInterceptorStacks(element, context);
+ }
+
+ // protected void loadPackages(Element rootElement) throws ConfigurationException {
+ // NodeList packageList = rootElement.getElementsByTagName("package");
+ //
+ // for (int i = 0; i < packageList.getLength(); i++) {
+ // Element packageElement = (Element) packageList.item(i);
+ // addPackage(packageElement);
+ // }
+ // }
+ private List<Document> loadConfigurationFiles(String fileName, Element includeElement) {
+ List<Document> docs = new ArrayList<Document>();
+ List<Document> finalDocs = new ArrayList<Document>();
+ if (!includedFileNames.contains(fileName)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Loading action configurations from: " + fileName);
+ }
+
+ includedFileNames.add(fileName);
+
+ Iterator<URL> urls = null;
+ InputStream is = null;
+
+ IOException ioException = null;
+ try {
+ urls = getConfigurationUrls(fileName);
+ } catch (IOException ex) {
+ ioException = ex;
+ }
+
+ if (urls == null || !urls.hasNext()) {
+ if (errorIfMissing) {
+ throw new ConfigurationException("Could not open files of the name " + fileName, ioException);
+ } else {
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Unable to locate configuration files of the name "
+ + fileName + ", skipping");
+ }
+ return docs;
+ }
+ }
+
+ URL url = null;
+ while (urls.hasNext()) {
+ try {
+ url = urls.next();
+ is = FileManager.loadFile(url);
+
+ InputSource in = new InputSource(is);
+
+ in.setSystemId(url.toString());
+
+ docs.add(DomHelper.parse(in, dtdMappings));
+ } catch (XWorkException e) {
+ if (includeElement != null) {
+ throw new ConfigurationException("Unable to load " + url, e, includeElement);
+ } else {
+ throw new ConfigurationException("Unable to load " + url, e);
+ }
+ } catch (Exception e) {
+ final String s = "Caught exception while loading file " + fileName;
+ throw new ConfigurationException(s, e, includeElement);
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ LOG.error("Unable to close input stream", e);
+ }
+ }
+ }
+ }
+
+ //sort the documents, according to the "order" attribute
+ Collections.sort(docs, new Comparator<Document>() {
+ public int compare(Document doc1, Document doc2) {
+ return XmlHelper.getLoadOrder(doc1).compareTo(XmlHelper.getLoadOrder(doc2));
+ }
+ });
+
+ for (Document doc : docs) {
+ Element rootElement = doc.getDocumentElement();
+ NodeList children = rootElement.getChildNodes();
+ int childSize = children.getLength();
+
+ for (int i = 0; i < childSize; i++) {
+ Node childNode = children.item(i);
+
+ if (childNode instanceof Element) {
+ Element child = (Element) childNode;
+
+ final String nodeName = child.getNodeName();
+
+ if ("include".equals(nodeName)) {
+ String includeFileName = child.getAttribute("file");
+ if (includeFileName.indexOf('*') != -1) {
+ // handleWildCardIncludes(includeFileName, docs, child);
+ ClassPathFinder wildcardFinder = new ClassPathFinder();
+ wildcardFinder.setPattern(includeFileName);
+ Vector<String> wildcardMatches = wildcardFinder.findMatches();
+ for (String match : wildcardMatches) {
+ finalDocs.addAll(loadConfigurationFiles(match, child));
+ }
+ } else {
+ finalDocs.addAll(loadConfigurationFiles(includeFileName, child));
+ }
+ }
+ }
+ }
+ finalDocs.add(doc);
+ loadedFileUrls.add(url.toString());
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Loaded action configuration from: " + fileName);
+ }
+ }
+ return finalDocs;
+ }
+
+ protected Iterator<URL> getConfigurationUrls(String fileName) throws IOException {
+ return ClassLoaderUtil.getResources(fileName, XmlConfigurationProvider.class, false);
+ }
+
+ /**
+ * Allows subclasses to load extra information from the document
+ *
+ * @param doc The configuration document
+ */
+ protected void loadExtraConfiguration(Document doc) {
+ // no op
+ }
+
+ /**
+ * Looks up the Interceptor Class from the interceptor-ref name and creates an instance, which is added to the
+ * provided List, or, if this is a ref to a stack, it adds the Interceptor instances from the List to this stack.
+ *
+ * @param interceptorRefElement Element to pull interceptor ref data from
+ * @param context The PackageConfig to lookup the interceptor from
+ * @return A list of Interceptor objects
+ */
+ private List<InterceptorMapping> lookupInterceptorReference(PackageConfig.Builder context, Element interceptorRefElement) throws ConfigurationException {
+ String refName = interceptorRefElement.getAttribute("name");
+ Map<String, String> refParams = XmlHelper.getParams(interceptorRefElement);
+
+ Location loc = LocationUtils.getLocation(interceptorRefElement);
+ return InterceptorBuilder.constructInterceptorReference(context, refName, refParams, loc, objectFactory);
+ }
+
+ List<Document> getDocuments() {
+ return documents;
+ }
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/providers/XmlHelper.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/providers/XmlHelper.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/providers/XmlHelper.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/providers/XmlHelper.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,128 @@
+/*
+ * 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 org.apache.struts2.xwork2.config.providers;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Document;
+import org.apache.commons.lang.StringUtils;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+
+/**
+ * XML utilities.
+ *
+ * @author Mike
+ */
+public class XmlHelper {
+
+
+ /**
+ * This method will find all the parameters under this <code>paramsElement</code> and return them as
+ * Map<String, String>. For example,
+ * <pre>
+ * <result ... >
+ * <param name="param1">value1</param>
+ * <param name="param2">value2</param>
+ * <param name="param3">value3</param>
+ * </result>
+ * </pre>
+ * will returns a Map<String, String> with the following key, value pairs :-
+ * <ul>
+ * <li>param1 - value1</li>
+ * <li>param2 - value2</li>
+ * <li>param3 - value3</li>
+ * </ul>
+ *
+ * @param paramsElement
+ * @return
+ */
+ public static Map<String, String> getParams(Element paramsElement) {
+ LinkedHashMap<String, String> params = new LinkedHashMap<String, String>();
+
+ if (paramsElement == null) {
+ return params;
+ }
+
+ NodeList childNodes = paramsElement.getChildNodes();
+
+ for (int i = 0; i < childNodes.getLength(); i++) {
+ Node childNode = childNodes.item(i);
+
+ if ((childNode.getNodeType() == Node.ELEMENT_NODE) && "param".equals(childNode.getNodeName())) {
+ Element paramElement = (Element) childNode;
+ String paramName = paramElement.getAttribute("name");
+
+ String val = getContent(paramElement);
+ if (val.length() > 0) {
+ params.put(paramName, val);
+ }
+ }
+ }
+
+ return params;
+ }
+
+ /**
+ * This method will return the content of this particular <code>element</code>.
+ * For example,
+ * <p/>
+ * <pre>
+ * <result>something_1</result>
+ * </pre>
+ * When the {@link org.w3c.dom.Element} <code><result></code> is passed in as
+ * argument (<code>element</code> to this method, it returns the content of it,
+ * namely, <code>something_1</code> in the example above.
+ *
+ * @return
+ */
+ public static String getContent(Element element) {
+ StringBuilder paramValue = new StringBuilder();
+ NodeList childNodes = element.getChildNodes();
+ for (int j = 0; j < childNodes.getLength(); j++) {
+ Node currentNode = childNodes.item(j);
+ if (currentNode != null &&
+ currentNode.getNodeType() == Node.TEXT_NODE) {
+ String val = currentNode.getNodeValue();
+ if (val != null) {
+ paramValue.append(val.trim());
+ }
+ }
+ }
+ return paramValue.toString().trim();
+ }
+
+ /**
+ * Return the value of the "order" attribute from the root element
+ */
+ public static Integer getLoadOrder(Document doc) {
+ Element rootElement = doc.getDocumentElement();
+ String number = rootElement.getAttribute("order");
+ if (StringUtils.isNotBlank(number)) {
+ try {
+ return Integer.parseInt(number);
+ } catch (NumberFormatException e) {
+ return Integer.MAX_VALUE;
+ }
+ } else {
+ //no order specified
+ return Integer.MAX_VALUE;
+ }
+ }
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/providers/package.html
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/providers/package.html?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/providers/package.html (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/config/providers/package.html Fri Dec 2 16:33:03 2011
@@ -0,0 +1 @@
+<body>Configuration provider classes.</body>
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/conversion/NullHandler.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/conversion/NullHandler.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/conversion/NullHandler.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/conversion/NullHandler.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,54 @@
+//--------------------------------------------------------------------------
+//Copyright (c) 1998-2004, Drew Davidson and Luke Blanshard
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions are
+//met:
+//
+//Redistributions of source code must retain the above copyright notice,
+//this list of conditions and the following disclaimer.
+//Redistributions in binary form must reproduce the above copyright
+//notice, this list of conditions and the following disclaimer in the
+//documentation and/or other materials provided with the distribution.
+//Neither the name of the Drew Davidson nor the names of its contributors
+//may be used to endorse or promote products derived from this software
+//without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+//OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+//AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+//OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+//THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+//DAMAGE.
+//--------------------------------------------------------------------------
+package org.apache.struts2.xwork2.conversion;
+
+import java.util.Map;
+
+/**
+* Interface for handling null results from Chains.
+* Object has the opportunity to substitute an object for the
+* null and continue.
+* @author Luke Blanshard (blanshlu@netscape.net)
+* @author Drew Davidson (drew@ognl.org)
+*/
+public interface NullHandler
+{
+ /**
+ Method called on target returned null.
+ */
+ public Object nullMethodResult(Map<String, Object> context, Object target, String methodName, Object[] args);
+
+ /**
+ Property in target evaluated to null. Property can be a constant
+ String property name or a DynamicSubscript.
+ */
+ public Object nullPropertyValue(Map<String, Object> context, Object target, Object property);
+}
\ No newline at end of file
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/conversion/ObjectTypeDeterminer.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/conversion/ObjectTypeDeterminer.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/conversion/ObjectTypeDeterminer.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/conversion/ObjectTypeDeterminer.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2002-2007,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 org.apache.struts2.xwork2.conversion;
+
+/**
+ * Determines what the key and and element class of a Map or Collection should be. For Maps, the elements are the
+ * values. For Collections, the elements are the elements of the collection.
+ * <p/>
+ * See the implementations for javadoc description for the methods as they are dependent on the concrete implementation.
+ *
+ * @author Gabriel Zimmerman
+ */
+public interface ObjectTypeDeterminer {
+
+ public Class getKeyClass(Class parentClass, String property);
+
+ public Class getElementClass(Class parentClass, String property, Object key);
+
+ public String getKeyProperty(Class parentClass, String property);
+
+ public boolean shouldCreateIfNew(Class parentClass, String property, Object target, String keyProperty, boolean isIndexAccessed);
+
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/conversion/TypeConversionException.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/conversion/TypeConversionException.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/conversion/TypeConversionException.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/conversion/TypeConversionException.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,61 @@
+/*
+ * 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 org.apache.struts2.xwork2.conversion;
+
+import org.apache.struts2.xwork2.XWorkException;
+
+
+/**
+ * TypeConversionException should be thrown by any TypeConverters which fail to convert values
+ *
+ * @author Jason Carreira
+ * Created Oct 3, 2003 12:18:33 AM
+ */
+public class TypeConversionException extends XWorkException {
+
+ /**
+ * Constructs a <code>XWorkException</code> with no detail message.
+ */
+ public TypeConversionException() {
+ }
+
+ /**
+ * Constructs a <code>XWorkException</code> with the specified
+ * detail message.
+ *
+ * @param s the detail message.
+ */
+ public TypeConversionException(String s) {
+ super(s);
+ }
+
+ /**
+ * Constructs a <code>XWorkException</code> with no detail message.
+ */
+ public TypeConversionException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs a <code>XWorkException</code> with the specified
+ * detail message.
+ *
+ * @param s the detail message.
+ */
+ public TypeConversionException(String s, Throwable cause) {
+ super(s, cause);
+ }
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/conversion/TypeConverter.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/conversion/TypeConverter.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/conversion/TypeConverter.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/conversion/TypeConverter.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,64 @@
+//--------------------------------------------------------------------------
+// Copyright (c) 1998-2004, Drew Davidson and Luke Blanshard
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// Neither the name of the Drew Davidson nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+//--------------------------------------------------------------------------
+package org.apache.struts2.xwork2.conversion;
+
+import java.lang.reflect.Member;
+import java.util.Map;
+
+/**
+ * Interface for accessing the type conversion facilities within a context.
+ *
+ * This interface was copied from OGNL's TypeConverter
+ *
+ * @author Luke Blanshard (blanshlu@netscape.net)
+ * @author Drew Davidson (drew@ognl.org)
+ */
+public interface TypeConverter
+{
+ /**
+ * Converts the given value to a given type. The OGNL context, target, member and
+ * name of property being set are given. This method should be able to handle
+ * conversion in general without any context, target, member or property name specified.
+ * @param context context under which the conversion is being done
+ * @param target target object in which the property is being set
+ * @param member member (Constructor, Method or Field) being set
+ * @param propertyName property name being set
+ * @param value value to be converted
+ * @param toType type to which value is converted
+ * @return Converted value of type toType or TypeConverter.NoConversionPossible to indicate that the
+ conversion was not possible.
+ */
+ public Object convertValue(Map<String, Object> context, Object target, Member member, String propertyName, Object value, Class toType);
+
+ public static final Object NO_CONVERSION_POSSIBLE = "ognl.NoConversionPossible";
+
+ public static final String TYPE_CONVERTER_CONTEXT_KEY = "_typeConverter";
+}
\ No newline at end of file