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 [25/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/ognl/accessor/XWorkMapPropertyAccessor.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/ognl/accessor/XWorkMapPropertyAccessor.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/ognl/accessor/XWorkMapPropertyAccessor.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/ognl/accessor/XWorkMapPropertyAccessor.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,176 @@
+/*
+ * 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.ognl.accessor;
+
+import org.apache.struts2.xwork2.ObjectFactory;
+import org.apache.struts2.xwork2.conversion.ObjectTypeDeterminer;
+import org.apache.struts2.xwork2.conversion.impl.XWorkConverter;
+import org.apache.struts2.xwork2.inject.Inject;
+import org.apache.struts2.xwork2.util.logging.Logger;
+import org.apache.struts2.xwork2.util.logging.LoggerFactory;
+import org.apache.struts2.xwork2.util.reflection.ReflectionContextState;
+import ognl.MapPropertyAccessor;
+import ognl.OgnlException;
+
+import java.util.Map;
+
+/**
+ * Implementation of PropertyAccessor that sets and gets properties by storing and looking
+ * up values in Maps.
+ *
+ * @author Gabriel Zimmerman
+ */
+public class XWorkMapPropertyAccessor extends MapPropertyAccessor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(XWorkMapPropertyAccessor.class);
+
+ private static final String[] INDEX_ACCESS_PROPS = new String[]
+ {"size", "isEmpty", "keys", "values"};
+
+ private XWorkConverter xworkConverter;
+ private ObjectFactory objectFactory;
+ private ObjectTypeDeterminer objectTypeDeterminer;
+
+ @Inject
+ public void setXWorkConverter(XWorkConverter conv) {
+ this.xworkConverter = conv;
+ }
+
+ @Inject
+ public void setObjectFactory(ObjectFactory fac) {
+ this.objectFactory = fac;
+ }
+
+ @Inject
+ public void setObjectTypeDeterminer(ObjectTypeDeterminer ot) {
+ this.objectTypeDeterminer = ot;
+ }
+
+ @Override
+ public Object getProperty(Map context, Object target, Object name) throws OgnlException {
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Entering getProperty ("+context+","+target+","+name+")");
+ }
+
+ ReflectionContextState.updateCurrentPropertyPath(context, name);
+ // if this is one of the regular index access
+ // properties then just let the superclass deal with the
+ // get.
+ if (name instanceof String && contains(INDEX_ACCESS_PROPS, (String) name)) {
+ return super.getProperty(context, target, name);
+ }
+
+ Object result = null;
+
+ try{
+ result = super.getProperty(context, target, name);
+ } catch(ClassCastException ex){
+ }
+
+ if (result == null) {
+ //find the key class and convert the name to that class
+ Class lastClass = (Class) context.get(XWorkConverter.LAST_BEAN_CLASS_ACCESSED);
+
+ String lastProperty = (String) context.get(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED);
+ if (lastClass == null || lastProperty == null) {
+ return super.getProperty(context, target, name);
+ }
+ Class keyClass = objectTypeDeterminer
+ .getKeyClass(lastClass, lastProperty);
+
+ if (keyClass == null) {
+
+ keyClass = java.lang.String.class;
+ }
+ Object key = getKey(context, name);
+ Map map = (Map) target;
+ result = map.get(key);
+
+ if (result == null &&
+ context.get(ReflectionContextState.CREATE_NULL_OBJECTS) != null
+ && objectTypeDeterminer.shouldCreateIfNew(lastClass,lastProperty,target,null,false)) {
+ Class valueClass = objectTypeDeterminer.getElementClass(lastClass, lastProperty, key);
+
+ try {
+ result = objectFactory.buildBean(valueClass, context);
+ map.put(key, result);
+ } catch (Exception exc) {
+
+ }
+
+ }
+ }
+ return result;
+ }
+
+ /**
+ * @param array
+ * @param name
+ */
+ private boolean contains(String[] array, String name) {
+ for (String anArray : array) {
+ if (anArray.equals(name)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Entering setProperty("+context+","+target+","+name+","+value+")");
+ }
+
+ Object key = getKey(context, name);
+ Map map = (Map) target;
+ map.put(key, getValue(context, value));
+ }
+
+ private Object getValue(Map context, Object value) {
+ Class lastClass = (Class) context.get(XWorkConverter.LAST_BEAN_CLASS_ACCESSED);
+ String lastProperty = (String) context.get(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED);
+ if (lastClass == null || lastProperty == null) {
+ return value;
+ }
+ Class elementClass = objectTypeDeterminer.getElementClass(lastClass, lastProperty, null);
+ if (elementClass == null) {
+ return value; // nothing is specified, we assume it will be the value passed in.
+ }
+ return xworkConverter.convertValue(context, value, elementClass);
+}
+
+ private Object getKey(Map context, Object name) {
+ Class lastClass = (Class) context.get(XWorkConverter.LAST_BEAN_CLASS_ACCESSED);
+ String lastProperty = (String) context.get(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED);
+ if (lastClass == null || lastProperty == null) {
+ // return java.lang.String.class;
+ // commented out the above -- it makes absolutely no sense for when setting basic maps!
+ return name;
+ }
+ Class keyClass = objectTypeDeterminer.getKeyClass(lastClass, lastProperty);
+ if (keyClass == null) {
+ keyClass = java.lang.String.class;
+ }
+
+ return xworkConverter.convertValue(context, name, keyClass);
+
+ }
+}
+
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/ognl/accessor/XWorkMethodAccessor.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/ognl/accessor/XWorkMethodAccessor.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/ognl/accessor/XWorkMethodAccessor.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/ognl/accessor/XWorkMethodAccessor.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,159 @@
+/*
+ * 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.ognl.accessor;
+
+import java.beans.PropertyDescriptor;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+
+import ognl.MethodFailedException;
+import ognl.ObjectMethodAccessor;
+import ognl.OgnlContext;
+import ognl.OgnlRuntime;
+import ognl.PropertyAccessor;
+
+import org.apache.struts2.xwork2.util.logging.Logger;
+import org.apache.struts2.xwork2.util.logging.LoggerFactory;
+import org.apache.struts2.xwork2.util.reflection.ReflectionContextState;
+
+
+/**
+ * Allows methods to be executed under normal cirumstances, except when {@link org.apache.struts2.xwork2.util.reflection.ReflectionContextState#DENY_METHOD_EXECUTION}
+ * is in the action context with a value of true.
+ *
+ * @author Patrick Lightbody
+ * @author tmjee
+ */
+public class XWorkMethodAccessor extends ObjectMethodAccessor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(XWorkMethodAccessor.class);
+
+ /**
+ * @deprecated Use {@link org.apache.struts2.xwork2.util.reflection.ReflectionContextState#DENY_METHOD_EXECUTION} instead
+ */
+ @Deprecated public static final String DENY_METHOD_EXECUTION = ReflectionContextState.DENY_METHOD_EXECUTION;
+ /**
+ * @deprecated Use {@link ReflectionContextState#DENY_INDEXED_ACCESS_EXECUTION} instead
+ */
+ @Deprecated public static final String DENY_INDEXED_ACCESS_EXECUTION = ReflectionContextState.DENY_INDEXED_ACCESS_EXECUTION;
+
+
+ @Override
+ public Object callMethod(Map context, Object object, String string, Object[] objects) throws MethodFailedException {
+
+ //Collection property accessing
+ //this if statement ensures that ognl
+ //statements of the form someBean.mySet('keyPropVal')
+ //return the set element with value of the keyProp given
+
+ if (objects.length==1
+ && context instanceof OgnlContext) {
+ try {
+ OgnlContext ogContext=(OgnlContext)context;
+ if (OgnlRuntime.hasSetProperty(ogContext, object, string)) {
+ PropertyDescriptor descriptor=OgnlRuntime.getPropertyDescriptor(object.getClass(), string);
+ Class propertyType=descriptor.getPropertyType();
+ if ((Collection.class).isAssignableFrom(propertyType)) {
+ //go directly through OgnlRuntime here
+ //so that property strings are not cleared
+ //i.e. OgnlUtil should be used initially, OgnlRuntime
+ //thereafter
+
+ Object propVal=OgnlRuntime.getProperty(ogContext, object, string);
+ //use the Collection property accessor instead of the individual property accessor, because
+ //in the case of Lists otherwise the index property could be used
+ PropertyAccessor accessor=OgnlRuntime.getPropertyAccessor(Collection.class);
+ ReflectionContextState.setGettingByKeyProperty(ogContext,true);
+ return accessor.getProperty(ogContext,propVal,objects[0]);
+ }
+ }
+ } catch (Exception oe) {
+ //this exception should theoretically never happen
+ //log it
+ LOG.error("An unexpected exception occurred", oe);
+ }
+
+ }
+
+ //HACK - we pass indexed method access i.e. setXXX(A,B) pattern
+ if (
+ (objects.length == 2 && string.startsWith("set"))
+ ||
+ (objects.length == 1 && string.startsWith("get"))
+ ) {
+ Boolean exec = (Boolean) context.get(ReflectionContextState.DENY_INDEXED_ACCESS_EXECUTION);
+ boolean e = ((exec == null) ? false : exec.booleanValue());
+ if (!e) {
+ return callMethodWithDebugInfo(context, object, string, objects);
+ }
+ }
+ Boolean exec = (Boolean) context.get(ReflectionContextState.DENY_METHOD_EXECUTION);
+ boolean e = ((exec == null) ? false : exec.booleanValue());
+
+ if (!e) {
+ return callMethodWithDebugInfo(context, object, string, objects);
+ } else {
+ return null;
+ }
+ }
+
+ private Object callMethodWithDebugInfo(Map context, Object object, String methodName,
+ Object[] objects) throws MethodFailedException {
+ try {
+ return super.callMethod(context, object, methodName, objects);
+ }
+ catch(MethodFailedException e) {
+ if (LOG.isDebugEnabled()) {
+ if (!(e.getReason() instanceof NoSuchMethodException)) {
+ // the method exists on the target object, but something went wrong
+ String s = "Error calling method through OGNL: object: [#0] method: [#1] args: [#2]";
+ LOG.debug(s, e.getReason(), object.toString(), methodName, Arrays.toString(objects));
+ }
+ }
+ throw e;
+ }
+ }
+
+ @Override
+ public Object callStaticMethod(Map context, Class aClass, String string, Object[] objects) throws MethodFailedException {
+ Boolean exec = (Boolean) context.get(ReflectionContextState.DENY_METHOD_EXECUTION);
+ boolean e = ((exec == null) ? false : exec.booleanValue());
+
+ if (!e) {
+ return callStaticMethodWithDebugInfo(context, aClass, string, objects);
+ } else {
+ return null;
+ }
+ }
+
+ private Object callStaticMethodWithDebugInfo(Map context, Class aClass, String methodName,
+ Object[] objects) throws MethodFailedException {
+ try {
+ return super.callStaticMethod(context, aClass, methodName, objects);
+ }
+ catch(MethodFailedException e) {
+ if (LOG.isDebugEnabled()) {
+ if (!(e.getReason() instanceof NoSuchMethodException)) {
+ // the method exists on the target class, but something went wrong
+ String s = "Error calling method through OGNL, class: [#0] method: [#1] args: [#2]";
+ LOG.debug(s, e.getReason(), aClass.getName(), methodName, Arrays.toString(objects));
+ }
+ }
+ throw e;
+ }
+ }
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/ognl/accessor/XWorkObjectPropertyAccessor.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/ognl/accessor/XWorkObjectPropertyAccessor.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/ognl/accessor/XWorkObjectPropertyAccessor.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/ognl/accessor/XWorkObjectPropertyAccessor.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,41 @@
+/*
+ * 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.ognl.accessor;
+
+import org.apache.struts2.xwork2.conversion.impl.XWorkConverter;
+import org.apache.struts2.xwork2.util.reflection.ReflectionContextState;
+import ognl.ObjectPropertyAccessor;
+import ognl.OgnlException;
+
+import java.util.Map;
+
+/**
+ * @author Gabe
+ */
+public class XWorkObjectPropertyAccessor extends ObjectPropertyAccessor {
+ @Override
+ public Object getProperty(Map context, Object target, Object oname)
+ throws OgnlException {
+ //set the last set objects in the context
+ //so if the next objects accessed are
+ //Maps or Collections they can use the information
+ //to determine conversion types
+ context.put(XWorkConverter.LAST_BEAN_CLASS_ACCESSED, target.getClass());
+ context.put(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED, oname.toString());
+ ReflectionContextState.updateCurrentPropertyPath(context, oname);
+ return super.getProperty(context, target, oname);
+ }
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/package.html
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/package.html?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/package.html (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/package.html Fri Dec 2 16:33:03 2011
@@ -0,0 +1 @@
+<body>Main XWork interfaces and classes.</body>
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/spring/SpringObjectFactory.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/spring/SpringObjectFactory.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/spring/SpringObjectFactory.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/spring/SpringObjectFactory.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,284 @@
+/*
+ * 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.spring;
+
+import org.apache.struts2.xwork2.ObjectFactory;
+import org.apache.struts2.xwork2.inject.Inject;
+import org.apache.struts2.xwork2.util.logging.Logger;
+import org.apache.struts2.xwork2.util.logging.LoggerFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.UnsatisfiedDependencyException;
+import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Simple implementation of the ObjectFactory that makes use of Spring's application context if one has been configured,
+ * before falling back on the default mechanism of instantiating a new class using the class name. <p/> In order to use
+ * this class in your application, you will need to instantiate a copy of this class and set it as XWork's ObjectFactory
+ * before the xwork.xml file is parsed. In a servlet environment, this could be done using a ServletContextListener.
+ *
+ * @author Simon Stewart (sms@lateral.net)
+ */
+public class SpringObjectFactory extends ObjectFactory implements ApplicationContextAware {
+ private static final Logger LOG = LoggerFactory.getLogger(SpringObjectFactory.class);
+
+ protected ApplicationContext appContext;
+ protected AutowireCapableBeanFactory autoWiringFactory;
+ protected int autowireStrategy = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
+ private final Map<String, Object> classes = new HashMap<String, Object>();
+ private boolean useClassCache = true;
+ private boolean alwaysRespectAutowireStrategy = false;
+
+ @Inject(value="applicationContextPath",required=false)
+ public void setApplicationContextPath(String ctx) {
+ if (ctx != null) {
+ setApplicationContext(new ClassPathXmlApplicationContext(ctx));
+ }
+ }
+
+ /**
+ * Set the Spring ApplicationContext that should be used to look beans up with.
+ *
+ * @param appContext The Spring ApplicationContext that should be used to look beans up with.
+ */
+ public void setApplicationContext(ApplicationContext appContext)
+ throws BeansException {
+ this.appContext = appContext;
+ autoWiringFactory = findAutoWiringBeanFactory(this.appContext);
+ }
+
+ /**
+ * Sets the autowiring strategy
+ *
+ * @param autowireStrategy
+ */
+ public void setAutowireStrategy(int autowireStrategy) {
+ switch (autowireStrategy) {
+ case AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT:
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Setting autowire strategy to autodetect");
+ }
+ this.autowireStrategy = autowireStrategy;
+ break;
+ case AutowireCapableBeanFactory.AUTOWIRE_BY_NAME:
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Setting autowire strategy to name");
+ }
+ this.autowireStrategy = autowireStrategy;
+ break;
+ case AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE:
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Setting autowire strategy to type");
+ }
+ this.autowireStrategy = autowireStrategy;
+ break;
+ case AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR:
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Setting autowire strategy to constructor");
+ }
+ this.autowireStrategy = autowireStrategy;
+ break;
+ case AutowireCapableBeanFactory.AUTOWIRE_NO:
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Setting autowire strategy to none");
+ }
+ this.autowireStrategy = autowireStrategy;
+ break;
+ default:
+ throw new IllegalStateException("Invalid autowire type set");
+ }
+ }
+
+ public int getAutowireStrategy() {
+ return autowireStrategy;
+ }
+
+
+ /**
+ * If the given context is assignable to AutowireCapbleBeanFactory or contains a parent or a factory that is, then
+ * set the autoWiringFactory appropriately.
+ *
+ * @param context
+ */
+ protected AutowireCapableBeanFactory findAutoWiringBeanFactory(ApplicationContext context) {
+ if (context instanceof AutowireCapableBeanFactory) {
+ // Check the context
+ return (AutowireCapableBeanFactory) context;
+ } else if (context instanceof ConfigurableApplicationContext) {
+ // Try and grab the beanFactory
+ return ((ConfigurableApplicationContext) context).getBeanFactory();
+ } else if (context.getParent() != null) {
+ // And if all else fails, try again with the parent context
+ return findAutoWiringBeanFactory(context.getParent());
+ }
+ return null;
+ }
+
+ /**
+ * Looks up beans using Spring's application context before falling back to the method defined in the {@link
+ * ObjectFactory}.
+ *
+ * @param beanName The name of the bean to look up in the application context
+ * @param extraContext
+ * @return A bean from Spring or the result of calling the overridden
+ * method.
+ * @throws Exception
+ */
+ @Override
+ public Object buildBean(String beanName, Map<String, Object> extraContext, boolean injectInternal) throws Exception {
+ Object o;
+
+ if (appContext.containsBean(beanName)) {
+ o = appContext.getBean(beanName);
+ } else {
+ Class beanClazz = getClassInstance(beanName);
+ o = buildBean(beanClazz, extraContext);
+ }
+ if (injectInternal) {
+ injectInternalBeans(o);
+ }
+ return o;
+ }
+
+ /**
+ * @param clazz
+ * @param extraContext
+ * @throws Exception
+ */
+ @Override
+ public Object buildBean(Class clazz, Map<String, Object> extraContext) throws Exception {
+ Object bean;
+
+ try {
+ // Decide to follow autowire strategy or use the legacy approach which mixes injection strategies
+ if (alwaysRespectAutowireStrategy) {
+ // Leave the creation up to Spring
+ bean = autoWiringFactory.createBean(clazz, autowireStrategy, false);
+ injectApplicationContext(bean);
+ return injectInternalBeans(bean);
+ } else {
+ bean = autoWiringFactory.autowire(clazz, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false);
+ bean = autoWiringFactory.applyBeanPostProcessorsBeforeInitialization(bean, bean.getClass().getName());
+ // We don't need to call the init-method since one won't be registered.
+ bean = autoWiringFactory.applyBeanPostProcessorsAfterInitialization(bean, bean.getClass().getName());
+ return autoWireBean(bean, autoWiringFactory);
+ }
+ } catch (UnsatisfiedDependencyException e) {
+ if (LOG.isErrorEnabled())
+ LOG.error("Error building bean", e);
+ // Fall back
+ return autoWireBean(super.buildBean(clazz, extraContext), autoWiringFactory);
+ }
+ }
+
+ public Object autoWireBean(Object bean) {
+ return autoWireBean(bean, autoWiringFactory);
+ }
+
+ /**
+ * @param bean
+ * @param autoWiringFactory
+ */
+ public Object autoWireBean(Object bean, AutowireCapableBeanFactory autoWiringFactory) {
+ if (autoWiringFactory != null) {
+ autoWiringFactory.autowireBeanProperties(bean,
+ autowireStrategy, false);
+ }
+ injectApplicationContext(bean);
+
+ injectInternalBeans(bean);
+
+ return bean;
+ }
+
+ private void injectApplicationContext(Object bean) {
+ if (bean instanceof ApplicationContextAware) {
+ ((ApplicationContextAware) bean).setApplicationContext(appContext);
+ }
+ }
+
+ public Class getClassInstance(String className) throws ClassNotFoundException {
+ Class clazz = null;
+ if (useClassCache) {
+ synchronized(classes) {
+ // this cache of classes is needed because Spring sucks at dealing with situations where the
+ // class instance changes
+ clazz = (Class) classes.get(className);
+ }
+ }
+
+ if (clazz == null) {
+ if (appContext.containsBean(className)) {
+ clazz = appContext.getBean(className).getClass();
+ } else {
+ clazz = super.getClassInstance(className);
+ }
+
+ if (useClassCache) {
+ synchronized(classes) {
+ classes.put(className, clazz);
+ }
+ }
+ }
+
+ return clazz;
+ }
+
+ /**
+ * This method sets the ObjectFactory used by XWork to this object. It's best used as the "init-method" of a Spring
+ * bean definition in order to hook Spring and XWork together properly (as an alternative to the
+ * org.apache.struts2.spring.lifecycle.SpringObjectFactoryListener)
+ * @deprecated Since 2.1 as it isn't necessary
+ */
+ @Deprecated public void initObjectFactory() {
+ // not necessary anymore
+ }
+
+ /**
+ * Allows for ObjectFactory implementations that support
+ * Actions without no-arg constructors.
+ *
+ * @return false
+ */
+ @Override
+ public boolean isNoArgConstructorRequired() {
+ return false;
+ }
+
+ /**
+ * Enable / disable caching of classes loaded by Spring.
+ *
+ * @param useClassCache
+ */
+ public void setUseClassCache(boolean useClassCache) {
+ this.useClassCache = useClassCache;
+ }
+
+ /**
+ * Determines if the autowire strategy is always followed when creating beans
+ *
+ * @param alwaysRespectAutowireStrategy True if the strategy is always used
+ */
+ public void setAlwaysRespectAutowireStrategy(boolean alwaysRespectAutowireStrategy) {
+ this.alwaysRespectAutowireStrategy = alwaysRespectAutowireStrategy;
+ }
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/spring/SpringProxyableObjectFactory.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/spring/SpringProxyableObjectFactory.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/spring/SpringProxyableObjectFactory.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/spring/SpringProxyableObjectFactory.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,98 @@
+/*
+ * 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.spring;
+
+import org.apache.struts2.xwork2.util.logging.Logger;
+import org.apache.struts2.xwork2.util.logging.LoggerFactory;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.context.ApplicationContext;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * SpringProxyableObjectFactory.
+ *
+ * @author Jason Carreira
+ */
+public class SpringProxyableObjectFactory extends SpringObjectFactory {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SpringProxyableObjectFactory.class);
+
+ private List<String> skipBeanNames = new ArrayList<String>();
+
+ @Override
+ public Object buildBean(String beanName, Map<String, Object> extraContext) throws Exception {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Building bean for name " + beanName);
+ }
+ if (!skipBeanNames.contains(beanName)) {
+ ApplicationContext anAppContext = getApplicationContext(extraContext);
+ try {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Trying the application context... appContext = " + anAppContext + ",\n bean name = " + beanName);
+ }
+ return anAppContext.getBean(beanName);
+ } catch (NoSuchBeanDefinitionException e) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Did not find bean definition for bean named " + beanName + ", creating a new one...");
+ }
+ if (autoWiringFactory instanceof BeanDefinitionRegistry) {
+ try {
+ Class clazz = Class.forName(beanName);
+ BeanDefinitionRegistry registry = (BeanDefinitionRegistry) autoWiringFactory;
+ RootBeanDefinition def = new RootBeanDefinition(clazz, autowireStrategy);
+ def.setSingleton(false);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Registering a new bean definition for class " + beanName);
+ }
+ registry.registerBeanDefinition(beanName,def);
+ try {
+ return anAppContext.getBean(beanName);
+ } catch (NoSuchBeanDefinitionException e2) {
+ if (LOG.isWarnEnabled()) {
+ LOG.warn("Could not register new bean definition for bean " + beanName);
+ }
+ skipBeanNames.add(beanName);
+ }
+ } catch (ClassNotFoundException e1) {
+ skipBeanNames.add(beanName);
+ }
+ }
+ }
+ }
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Returning autowired instance created by default ObjectFactory");
+ }
+ return autoWireBean(super.buildBean(beanName, extraContext), autoWiringFactory);
+ }
+
+ /**
+ * Subclasses may override this to return a different application context.
+ * Note that this application context should see any changes made to the
+ * <code>autoWiringFactory</code>, so the application context should be either
+ * the original or a child context of the original.
+ *
+ * @param context provided context.
+ */
+ protected ApplicationContext getApplicationContext(Map<String, Object> context) {
+ return appContext;
+ }
+}
+
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/spring/interceptor/ActionAutowiringInterceptor.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/spring/interceptor/ActionAutowiringInterceptor.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/spring/interceptor/ActionAutowiringInterceptor.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/spring/interceptor/ActionAutowiringInterceptor.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,138 @@
+/*
+ * 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.spring.interceptor;
+
+import org.apache.struts2.xwork2.ActionContext;
+import org.apache.struts2.xwork2.ActionInvocation;
+import org.apache.struts2.xwork2.interceptor.AbstractInterceptor;
+import org.apache.struts2.xwork2.spring.SpringObjectFactory;
+import org.apache.struts2.xwork2.util.logging.Logger;
+import org.apache.struts2.xwork2.util.logging.LoggerFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.web.context.WebApplicationContext;
+
+/**
+ * <!-- START SNIPPET: description -->
+ * TODO: Give a description of the Interceptor.
+ * <!-- END SNIPPET: description -->
+ *
+ * <!-- START SNIPPET: parameters -->
+ * TODO: Describe the paramters for this Interceptor.
+ * <!-- END SNIPPET: parameters -->
+ *
+ * <!-- START SNIPPET: extending -->
+ * TODO: Discuss some possible extension of the Interceptor.
+ * <!-- END SNIPPET: extending -->
+ *
+ * <pre>
+ * <!-- START SNIPPET: example -->
+ * <!-- TODO: Describe how the Interceptor reference will effect execution -->
+ * <action name="someAction" class="com.examples.SomeAction">
+ * TODO: fill in the interceptor reference.
+ * <interceptor-ref name=""/>
+ * <result name="success">good_result.ftl</result>
+ * </action>
+ * <!-- END SNIPPET: example -->
+ * </pre>
+ *
+ * Autowires action classes to Spring beans. The strategy for autowiring the beans can be configured
+ * by setting the parameter on the interceptor. Actions that need access to the <code>ActionContext</code>
+ * can implements the <code>ApplicationContextAware</code> interface. The context will also be placed on
+ * the action context under the APPLICATION_CONTEXT attribute.
+ *
+ * @author Simon Stewart
+ * @author Eric Hauser
+ */
+public class ActionAutowiringInterceptor extends AbstractInterceptor implements ApplicationContextAware {
+ private static final Logger LOG = LoggerFactory.getLogger(ActionAutowiringInterceptor.class);
+
+ public static final String APPLICATION_CONTEXT = "org.apache.struts2.xwork2.spring.interceptor.ActionAutowiringInterceptor.applicationContext";
+
+ private boolean initialized = false;
+ private ApplicationContext context;
+ private SpringObjectFactory factory;
+ private Integer autowireStrategy;
+
+ /**
+ * @param autowireStrategy
+ */
+ public void setAutowireStrategy(Integer autowireStrategy) {
+ this.autowireStrategy = autowireStrategy;
+ }
+
+ /**
+ * Looks for the <code>ApplicationContext</code> under the attribute that the Spring listener sets in
+ * the servlet context. The configuration is done the first time here instead of in init() since the
+ * <code>ActionContext</code> is not available during <code>Interceptor</code> initialization.
+ * <p/>
+ * Autowires the action to Spring beans and places the <code>ApplicationContext</code>
+ * on the <code>ActionContext</code>
+ * <p/>
+ * TODO Should this check to see if the <code>SpringObjectFactory</code> has already been configured
+ * instead of instantiating a new one? Or is there a good reason for the interceptor to have it's own
+ * factory?
+ *
+ * @param invocation
+ * @throws Exception
+ */
+ @Override public String intercept(ActionInvocation invocation) throws Exception {
+ if (!initialized) {
+ ApplicationContext applicationContext = (ApplicationContext) ActionContext.getContext().getApplication().get(
+ WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
+
+ if (applicationContext == null) {
+ if (LOG.isWarnEnabled()) {
+ LOG.warn("ApplicationContext could not be found. Action classes will not be autowired.");
+ }
+ } else {
+ setApplicationContext(applicationContext);
+ factory = new SpringObjectFactory();
+ factory.setApplicationContext(getApplicationContext());
+ if (autowireStrategy != null) {
+ factory.setAutowireStrategy(autowireStrategy.intValue());
+ }
+ }
+ initialized = true;
+ }
+
+ if (factory != null) {
+ Object bean = invocation.getAction();
+ factory.autoWireBean(bean);
+
+ ActionContext.getContext().put(APPLICATION_CONTEXT, context);
+ }
+ return invocation.invoke();
+ }
+
+ /**
+ * @param applicationContext
+ * @throws BeansException
+ */
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ context = applicationContext;
+ }
+
+ /**
+ * @return context
+ */
+ protected ApplicationContext getApplicationContext() {
+ return context;
+ }
+
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/spring/interceptor/package.html
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/spring/interceptor/package.html?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/spring/interceptor/package.html (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/spring/interceptor/package.html Fri Dec 2 16:33:03 2011
@@ -0,0 +1 @@
+<body>Spring specific interceptor classes.</body>
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/spring/package.html
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/spring/package.html?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/spring/package.html (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/spring/package.html Fri Dec 2 16:33:03 2011
@@ -0,0 +1 @@
+<body>Spring ObjectFactory classes.</body>
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/test/StubConfigurationProvider.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/test/StubConfigurationProvider.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/test/StubConfigurationProvider.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/test/StubConfigurationProvider.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,36 @@
+package org.apache.struts2.xwork2.test;
+
+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.inject.ContainerBuilder;
+import org.apache.struts2.xwork2.util.location.LocatableProperties;
+
+public class StubConfigurationProvider implements ConfigurationProvider {
+
+ public void destroy() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void init(Configuration configuration) throws ConfigurationException {
+ // TODO Auto-generated method stub
+ }
+
+ public void loadPackages() throws ConfigurationException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public boolean needsReload() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void register(ContainerBuilder builder, LocatableProperties props)
+ throws ConfigurationException {
+ // TODO Auto-generated method stub
+
+ }
+
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/AnnotationUtils.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/AnnotationUtils.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/AnnotationUtils.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/AnnotationUtils.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,227 @@
+/*
+ * 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.util;
+
+import java.io.File;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * <code>AnnotationUtils</code>
+ *
+ * Various utility methods dealing with annotations
+ *
+ * @author Rainer Hermanns
+ * @author Zsolt Szasz, zsolt at lorecraft dot com
+ * @author Dan Oxlade, dan d0t oxlade at gmail d0t c0m
+ * @version $Id: AnnotationUtils.java 1209415 2011-12-02 11:24:48Z lukaszlenart $
+ */
+public class AnnotationUtils {
+
+ private static final Pattern SETTER_PATTERN = Pattern.compile("set([A-Z][A-Za-z0-9]*)$");
+ private static final Pattern GETTER_PATTERN = Pattern.compile("(get|is|has)([A-Z][A-Za-z0-9]*)$");
+
+
+
+ /**
+ * Adds all fields with the specified Annotation of class clazz and its superclasses to allFields
+ *
+ * @param annotationClass
+ * @param clazz
+ * @param allFields
+ */
+ public static void addAllFields(Class annotationClass, Class clazz, List<Field> allFields) {
+
+ if (clazz == null) {
+ return;
+ }
+
+ Field[] fields = clazz.getDeclaredFields();
+
+ for (Field field : fields) {
+ Annotation ann = field.getAnnotation(annotationClass);
+ if (ann!=null) {
+ allFields.add(field);
+ }
+ }
+ addAllFields(annotationClass, clazz.getSuperclass(), allFields);
+ }
+
+ /**
+ * Adds all methods with the specified Annotation of class clazz and its superclasses to allFields
+ *
+ * @param annotationClass
+ * @param clazz
+ * @param allMethods
+ */
+ public static void addAllMethods(Class annotationClass, Class clazz, List<Method> allMethods) {
+
+ if (clazz == null) {
+ return;
+ }
+
+ Method[] methods = clazz.getDeclaredMethods();
+
+ for (Method method : methods) {
+ Annotation ann = method.getAnnotation(annotationClass);
+ if (ann!=null) {
+ allMethods.add(method);
+ }
+ }
+ addAllMethods(annotationClass, clazz.getSuperclass(), allMethods);
+ }
+
+ /**
+ *
+ * @param clazz
+ * @param allInterfaces
+ */
+ public static void addAllInterfaces(Class clazz, List<Class> allInterfaces) {
+ if (clazz == null) {
+ return;
+ }
+
+ Class[] interfaces = clazz.getInterfaces();
+ allInterfaces.addAll(Arrays.asList(interfaces));
+ addAllInterfaces(clazz.getSuperclass(), allInterfaces);
+ }
+
+ /**
+ * For the given <code>Class</code> get a collection of the the {@link AnnotatedElement}s
+ * that match the given <code>annotation</code>s or if no <code>annotation</code>s are
+ * specified then return all of the annotated elements of the given <code>Class</code>.
+ * Includes only the method level annotations.
+ *
+ * @param clazz The {@link Class} to inspect
+ * @param annotation the {@link Annotation}s to find
+ * @return A {@link Collection}<{@link AnnotatedElement}> containing all of the
+ * method {@link AnnotatedElement}s matching the specified {@link Annotation}s
+ */
+ public static final Collection<Method> getAnnotatedMethods(Class clazz, Class<? extends Annotation>... annotation){
+ Collection<Method> toReturn = new HashSet<Method>();
+
+ for(Method m : clazz.getMethods()){
+ if( ArrayUtils.isNotEmpty(annotation) && isAnnotatedBy(m,annotation) ){
+ toReturn.add(m);
+ }else if( ArrayUtils.isEmpty(annotation) && ArrayUtils.isNotEmpty(m.getAnnotations())){
+ toReturn.add(m);
+ }
+ }
+
+ return toReturn;
+ }
+
+ /**
+ * Varargs version of <code>AnnotatedElement.isAnnotationPresent()</code>
+ * @see AnnotatedElement
+ */
+ public static final boolean isAnnotatedBy(AnnotatedElement annotatedElement, Class<? extends Annotation>... annotation) {
+ if(ArrayUtils.isEmpty(annotation)) return false;
+
+ for( Class<? extends Annotation> c : annotation ){
+ if( annotatedElement.isAnnotationPresent(c) ) return true;
+ }
+
+ return false;
+ }
+
+ /**
+ *
+ * @deprecated since 2.0.4 use getAnnotatedMethods
+ */
+ @Deprecated
+ public static List<Method> findAnnotatedMethods(Class clazz, Class<? extends Annotation> annotationClass) {
+ List<Method> methods = new ArrayList<Method>();
+ findRecursively(clazz, annotationClass, methods);
+ return methods;
+ }
+
+ /**
+ *
+ * @deprecated since 2.0.4 use getAnnotatedMethods
+ */
+ @Deprecated
+ public static void findRecursively(Class clazz, Class<? extends Annotation> annotationClass, List<Method> methods) {
+ for (Method m : clazz.getDeclaredMethods()) {
+ if (m.getAnnotation(annotationClass) != null) { methods.add(0, m); }
+ }
+ if (clazz.getSuperclass() != Object.class) {
+ findRecursively(clazz.getSuperclass(), annotationClass, methods);
+ }
+ }
+
+ /**
+ * Returns the property name for a method.
+ * This method is independant from property fields.
+ *
+ * @param method The method to get the property name for.
+ * @return the property name for given method; null if non could be resolved.
+ */
+ public static String resolvePropertyName(Method method) {
+
+ Matcher matcher = SETTER_PATTERN.matcher(method.getName());
+ if (matcher.matches() && method.getParameterTypes().length == 1) {
+ String raw = matcher.group(1);
+ return raw.substring(0, 1).toLowerCase() + raw.substring(1);
+ }
+
+ matcher = GETTER_PATTERN.matcher(method.getName());
+ if (matcher.matches() && method.getParameterTypes().length == 0) {
+ String raw = matcher.group(2);
+ return raw.substring(0, 1).toLowerCase() + raw.substring(1);
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Retrieves all classes within a packages.
+ * TODO: this currently does not work with jars.
+ *
+ * @param pckgname
+ * @return Array of full qualified class names from this package.
+ */
+ public static String[] find(Class clazz, final String pckgname) {
+
+ List<String> classes = new ArrayList<String>();
+ String name = new String(pckgname);
+ if (!name.startsWith("/")) {
+ name = "/" + name;
+ }
+
+ name = name.replace('.', File.separatorChar);
+
+ final URL url = clazz.getResource(name);
+ final File directory = new File(url.getFile());
+
+ if (directory.exists()) {
+ final String[] files = directory.list();
+ for (String file : files) {
+ if (file.endsWith(".class")) {
+ classes.add(pckgname + "." + file.substring(0, file.length() - 6));
+ }
+ }
+ }
+ return classes.toArray(new String[classes.size()]);
+ }
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/ArrayUtils.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/ArrayUtils.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/ArrayUtils.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/ArrayUtils.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,31 @@
+/*
+ * 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.util;
+
+/**
+ * @author Dan Oxlade, dan d0t oxlade at gmail d0t c0m
+ */
+public class ArrayUtils {
+
+ public static boolean isEmpty(Object[] array) {
+ return null == array || array.length == 0;
+ }
+
+ public static boolean isNotEmpty(Object[] array) {
+ return !isEmpty(array);
+ }
+
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/ClassLoaderUtil.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/ClassLoaderUtil.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/ClassLoaderUtil.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/ClassLoaderUtil.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2002-2003,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.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.*;
+
+
+/**
+ * This class is extremely useful for loading resources and classes in a fault tolerant manner
+ * that works across different applications servers.
+ *
+ * It has come out of many months of frustrating use of multiple application servers at Atlassian,
+ * please don't change things unless you're sure they're not going to break in one server or another!
+ *
+ * It was brought in from oscore trunk revision 147.
+ *
+ * @author $Author: lukaszlenart $
+ * @version $Revision: 1209415 $
+ */
+public class ClassLoaderUtil {
+ //~ Methods ////////////////////////////////////////////////////////////////
+
+ /**
+ * Load all resources with a given name, potentially aggregating all results
+ * from the searched classloaders. If no results are found, the resource name
+ * is prepended by '/' and tried again.
+ *
+ * This method will try to load the resources using the following methods (in order):
+ * <ul>
+ * <li>From Thread.currentThread().getContextClassLoader()
+ * <li>From ClassLoaderUtil.class.getClassLoader()
+ * <li>callingClass.getClassLoader()
+ * </ul>
+ *
+ * @param resourceName The name of the resources to load
+ * @param callingClass The Class object of the calling object
+ */
+ public static Iterator<URL> getResources(String resourceName, Class callingClass, boolean aggregate) throws IOException {
+
+ AggregateIterator<URL> iterator = new AggregateIterator<URL>();
+
+ iterator.addEnumeration(Thread.currentThread().getContextClassLoader().getResources(resourceName));
+
+ if (!iterator.hasNext() || aggregate) {
+ iterator.addEnumeration(ClassLoaderUtil.class.getClassLoader().getResources(resourceName));
+ }
+
+ if (!iterator.hasNext() || aggregate) {
+ ClassLoader cl = callingClass.getClassLoader();
+
+ if (cl != null) {
+ iterator.addEnumeration(cl.getResources(resourceName));
+ }
+ }
+
+ if (!iterator.hasNext() && (resourceName != null) && ((resourceName.length() == 0) || (resourceName.charAt(0) != '/'))) {
+ return getResources('/' + resourceName, callingClass, aggregate);
+ }
+
+ return iterator;
+ }
+
+ /**
+ * Load a given resource.
+ *
+ * This method will try to load the resource using the following methods (in order):
+ * <ul>
+ * <li>From Thread.currentThread().getContextClassLoader()
+ * <li>From ClassLoaderUtil.class.getClassLoader()
+ * <li>callingClass.getClassLoader()
+ * </ul>
+ *
+ * @param resourceName The name IllegalStateException("Unable to call ")of the resource to load
+ * @param callingClass The Class object of the calling object
+ */
+ public static URL getResource(String resourceName, Class callingClass) {
+ URL url = Thread.currentThread().getContextClassLoader().getResource(resourceName);
+
+ if (url == null) {
+ url = ClassLoaderUtil.class.getClassLoader().getResource(resourceName);
+ }
+
+ if (url == null) {
+ ClassLoader cl = callingClass.getClassLoader();
+
+ if (cl != null) {
+ url = cl.getResource(resourceName);
+ }
+ }
+
+ if ((url == null) && (resourceName != null) && ((resourceName.length() == 0) || (resourceName.charAt(0) != '/'))) {
+ return getResource('/' + resourceName, callingClass);
+ }
+
+ return url;
+ }
+
+ /**
+ * This is a convenience method to load a resource as a stream.
+ *
+ * The algorithm used to find the resource is given in getResource()
+ *
+ * @param resourceName The name of the resource to load
+ * @param callingClass The Class object of the calling object
+ */
+ public static InputStream getResourceAsStream(String resourceName, Class callingClass) {
+ URL url = getResource(resourceName, callingClass);
+
+ try {
+ return (url != null) ? url.openStream() : null;
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Load a class with a given name.
+ *
+ * It will try to load the class in the following order:
+ * <ul>
+ * <li>From Thread.currentThread().getContextClassLoader()
+ * <li>Using the basic Class.forName()
+ * <li>From ClassLoaderUtil.class.getClassLoader()
+ * <li>From the callingClass.getClassLoader()
+ * </ul>
+ *
+ * @param className The name of the class to load
+ * @param callingClass The Class object of the calling object
+ * @throws ClassNotFoundException If the class cannot be found anywhere.
+ */
+ public static Class loadClass(String className, Class callingClass) throws ClassNotFoundException {
+ try {
+ return Thread.currentThread().getContextClassLoader().loadClass(className);
+ } catch (ClassNotFoundException e) {
+ try {
+ return Class.forName(className);
+ } catch (ClassNotFoundException ex) {
+ try {
+ return ClassLoaderUtil.class.getClassLoader().loadClass(className);
+ } catch (ClassNotFoundException exc) {
+ return callingClass.getClassLoader().loadClass(className);
+ }
+ }
+ }
+ }
+
+ /**
+ * Aggregates Enumeration instances into one iterator and filters out duplicates. Always keeps one
+ * ahead of the enumerator to protect against returning duplicates.
+ */
+ static class AggregateIterator<E> implements Iterator<E> {
+
+ LinkedList<Enumeration<E>> enums = new LinkedList<Enumeration<E>>();
+ Enumeration<E> cur = null;
+ E next = null;
+ Set<E> loaded = new HashSet<E>();
+
+ public AggregateIterator<E> addEnumeration(Enumeration<E> e) {
+ if (e.hasMoreElements()) {
+ if (cur == null) {
+ cur = e;
+ next = e.nextElement();
+ loaded.add(next);
+ } else {
+ enums.add(e);
+ }
+ }
+ return this;
+ }
+
+ public boolean hasNext() {
+ return (next != null);
+ }
+
+ public E next() {
+ if (next != null) {
+ E prev = next;
+ next = loadNext();
+ return prev;
+ } else {
+ throw new NoSuchElementException();
+ }
+ }
+
+ private Enumeration<E> determineCurrentEnumeration() {
+ if (cur != null && !cur.hasMoreElements()) {
+ if (enums.size() > 0) {
+ cur = enums.removeLast();
+ } else {
+ cur = null;
+ }
+ }
+ return cur;
+ }
+
+ private E loadNext() {
+ if (determineCurrentEnumeration() != null) {
+ E tmp = cur.nextElement();
+ int loadedSize = loaded.size();
+ while (loaded.contains(tmp)) {
+ tmp = loadNext();
+ if (tmp == null || loaded.size() > loadedSize) {
+ break;
+ }
+ }
+ if (tmp != null) {
+ loaded.add(tmp);
+ }
+ return tmp;
+ }
+ return null;
+
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/ClassPathFinder.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/ClassPathFinder.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/ClassPathFinder.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/ClassPathFinder.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,177 @@
+/*
+ * $Id: ClassPathFinder.java 1209415 2011-12-02 11:24:48Z lukaszlenart $
+ *
+ * Copyright 2003-2004 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.util;
+
+import org.apache.struts2.xwork2.XWorkException;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.HashMap;
+import java.util.Vector;
+
+/**
+ * This class is an utility class that will search through the classpath
+ * for files whose names match the given pattern. The filename is tested
+ * using the given implementation of {@link PatternMatcher} by default it
+ * uses {@link WildcardHelper}
+ *
+ * @version $Rev: 1209415 $ $Date: 2011-12-02 12:24:48 +0100 (Fri, 02 Dec 2011) $
+ */
+public class ClassPathFinder {
+
+ /**
+ * The String pattern to test against.
+ */
+ private String pattern ;
+
+ private int[] compiledPattern ;
+
+ /**
+ * The PatternMatcher implementation to use
+ */
+ private PatternMatcher<int[]> patternMatcher = new WildcardHelper();
+
+ private Vector<String> compared = new Vector<String>();
+
+ /**
+ * retrieves the pattern in use
+ */
+ public String getPattern() {
+ return pattern;
+ }
+
+ /**
+ * sets the String pattern for comparing filenames
+ * @param pattern
+ */
+ public void setPattern(String pattern) {
+ this.pattern = pattern;
+ }
+
+ /**
+ * Builds a {@link java.util.Vector} containing Strings which each name a file
+ * who's name matches the pattern set by setPattern(String). The classpath is
+ * searched recursively, so use with caution.
+ *
+ * @return Vector<String> containing matching filenames
+ */
+ public Vector<String> findMatches() {
+ Vector<String> matches = new Vector<String>();
+ URLClassLoader cl = getURLClassLoader();
+ if (cl == null ) {
+ throw new XWorkException("unable to attain an URLClassLoader") ;
+ }
+ URL[] parentUrls = cl.getURLs();
+ compiledPattern = (int[]) patternMatcher.compilePattern(pattern);
+ for (URL url : parentUrls) {
+ if (!"file".equals(url.getProtocol())) {
+ continue ;
+ }
+ URI entryURI ;
+ try {
+ entryURI = url.toURI();
+ } catch (URISyntaxException e) {
+ continue;
+ }
+ File entry = new File(entryURI) ;
+ Vector<String> results = checkEntries(entry.list(), entry, "");
+ if (results != null ) {
+ matches.addAll(results);
+ }
+ }
+ return matches;
+ }
+
+ private Vector<String> checkEntries(String[] entries, File parent, String prefix) {
+
+ if (entries == null ) {
+ return null;
+ }
+
+ Vector<String> matches = new Vector<String>();
+ for (String listEntry : entries) {
+ File tempFile ;
+ if (!"".equals(prefix) ) {
+ tempFile = new File(parent, prefix + "/" + listEntry);
+ }
+ else {
+ tempFile = new File(parent, listEntry);
+ }
+ if (tempFile.isDirectory() &&
+ !(".".equals(listEntry) || "..".equals(listEntry)) ) {
+ if (!"".equals(prefix) ) {
+ matches.addAll(checkEntries(tempFile.list(), parent, prefix + "/" + listEntry));
+ }
+ else {
+ matches.addAll(checkEntries(tempFile.list(), parent, listEntry));
+ }
+ }
+ else {
+
+ String entryToCheck ;
+ if ("".equals(prefix)) {
+ entryToCheck = listEntry ;
+ }
+ else {
+ entryToCheck = prefix + "/" + listEntry ;
+ }
+
+ if (compared.contains(entryToCheck) ) {
+ continue;
+ }
+ else {
+ compared.add(entryToCheck) ;
+ }
+
+ boolean doesMatch = patternMatcher.match(new HashMap<String,String>(), entryToCheck, compiledPattern);
+ if (doesMatch) {
+ matches.add(entryToCheck);
+ }
+ }
+ }
+ return matches ;
+ }
+
+ /**
+ * sets the PatternMatcher implementation to use when comparing filenames
+ * @param patternMatcher
+ */
+ public void setPatternMatcher(PatternMatcher<int[]> patternMatcher) {
+ this.patternMatcher = patternMatcher;
+ }
+
+ private URLClassLoader getURLClassLoader() {
+ URLClassLoader ucl = null;
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+
+ if(! (loader instanceof URLClassLoader)) {
+ loader = ClassPathFinder.class.getClassLoader();
+ if (loader instanceof URLClassLoader) {
+ ucl = (URLClassLoader) loader ;
+ }
+ }
+ else {
+ ucl = (URLClassLoader) loader;
+ }
+
+ return ucl ;
+ }
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/ClearableValueStack.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/ClearableValueStack.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/ClearableValueStack.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/ClearableValueStack.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,29 @@
+/*
+ * $Id: ClearableValueStack.java 1209415 2011-12-02 11:24:48Z lukaszlenart $
+ *
+ * Copyright 2003-2004 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.util;
+
+/**
+ * ValueStacks implementing this interface provide a way to remove values from
+ * their contexts.
+ */
+public interface ClearableValueStack {
+ /**
+ * Remove all values from the context
+ */
+ void clearContextValues();
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/CompoundRoot.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/CompoundRoot.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/CompoundRoot.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/CompoundRoot.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,53 @@
+/*
+ * 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.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * A Stack that is implemented using a List.
+ *
+ * @author plightbo
+ * @version $Revision: 1209415 $
+ */
+public class CompoundRoot extends ArrayList {
+
+ public CompoundRoot() {
+ }
+
+ public CompoundRoot(List list) {
+ super(list);
+ }
+
+
+ public CompoundRoot cutStack(int index) {
+ return new CompoundRoot(subList(index, size()));
+ }
+
+ public Object peek() {
+ return get(0);
+ }
+
+ public Object pop() {
+ return remove(0);
+ }
+
+ public void push(Object o) {
+ add(0, o);
+ }
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/CreateIfNull.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/CreateIfNull.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/CreateIfNull.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/CreateIfNull.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,77 @@
+/*
+ * 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.util;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * <!-- START SNIPPET: description -->
+ * <p/>Sets the CreateIfNull for type conversion.
+ * <!-- END SNIPPET: description -->
+ *
+ * <p/> <u>Annotation usage:</u>
+ *
+ * <!-- START SNIPPET: usage -->
+ * <p/>The CreateIfNull annotation must be applied at field or method level.
+ * <!-- END SNIPPET: usage -->
+ * <p/> <u>Annotation parameters:</u>
+ *
+ * <!-- START SNIPPET: parameters -->
+ * <table>
+ * <thead>
+ * <tr>
+ * <th>Parameter</th>
+ * <th>Required</th>
+ * <th>Default</th>
+ * <th>Description</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td>value</td>
+ * <td>no</td>
+ * <td>false</td>
+ * <td>The CreateIfNull property value.</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ * <!-- END SNIPPET: parameters -->
+ *
+ * <p/> <u>Example code:</u>
+ * <pre>
+ * <!-- START SNIPPET: example -->
+ * @CreateIfNull( value = true )
+ * private List<User> users;
+ * <!-- END SNIPPET: example -->
+ * </pre>
+ *
+ * @author Rainer Hermanns
+ * @version $Id: CreateIfNull.java 1209415 2011-12-02 11:24:48Z lukaszlenart $
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.METHOD})
+public @interface CreateIfNull {
+
+ /**
+ * The CreateIfNull value.
+ * Defaults to <tt>true</tt>.
+ */
+ boolean value() default true;
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/DomHelper.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/DomHelper.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/DomHelper.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/util/DomHelper.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,366 @@
+/*
+ * Copyright 1999-2005 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.util;
+
+import org.apache.struts2.xwork2.ObjectFactory;
+import org.apache.struts2.xwork2.XWorkException;
+import org.apache.struts2.xwork2.util.location.Location;
+import org.apache.struts2.xwork2.util.location.LocationAttributes;
+import org.apache.struts2.xwork2.util.logging.Logger;
+import org.apache.struts2.xwork2.util.logging.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.*;
+import org.xml.sax.helpers.DefaultHandler;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import java.util.Map;
+
+/**
+ * Helper class to create and retrieve information from location-enabled
+ * DOM-trees.
+ *
+ * @since 1.2
+ */
+public class DomHelper {
+
+ private static final Logger LOG = LoggerFactory.getLogger(DomHelper.class);
+
+ public static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/";
+
+ public static Location getLocationObject(Element element) {
+ return LocationAttributes.getLocation(element);
+ }
+
+
+ /**
+ * Creates a W3C Document that remembers the location of each element in
+ * the source file. The location of element nodes can then be retrieved
+ * using the {@link #getLocationObject(Element)} method.
+ *
+ * @param inputSource the inputSource to read the document from
+ */
+ public static Document parse(InputSource inputSource) {
+ return parse(inputSource, null);
+ }
+
+
+ /**
+ * Creates a W3C Document that remembers the location of each element in
+ * the source file. The location of element nodes can then be retrieved
+ * using the {@link #getLocationObject(Element)} method.
+ *
+ * @param inputSource the inputSource to read the document from
+ * @param dtdMappings a map of DTD names and public ids
+ */
+ public static Document parse(InputSource inputSource, Map<String, String> dtdMappings) {
+
+ SAXParserFactory factory = null;
+ String parserProp = System.getProperty("xwork.saxParserFactory");
+ if (parserProp != null) {
+ try {
+ Class clazz = ObjectFactory.getObjectFactory().getClassInstance(parserProp);
+ factory = (SAXParserFactory) clazz.newInstance();
+ }
+ catch (ClassNotFoundException e) {
+ LOG.error("Unable to load saxParserFactory set by system property 'xwork.saxParserFactory': " + parserProp, e);
+ }
+ catch (Exception e) {
+ LOG.error("Unable to load saxParserFactory set by system property 'xwork.saxParserFactory': " + parserProp, e);
+ }
+ }
+
+ if (factory == null) {
+ factory = SAXParserFactory.newInstance();
+ }
+
+ factory.setValidating((dtdMappings != null));
+ factory.setNamespaceAware(true);
+
+ SAXParser parser = null;
+ try {
+ parser = factory.newSAXParser();
+ } catch (Exception ex) {
+ throw new XWorkException("Unable to create SAX parser", ex);
+ }
+
+
+ DOMBuilder builder = new DOMBuilder();
+
+ // Enhance the sax stream with location information
+ ContentHandler locationHandler = new LocationAttributes.Pipe(builder);
+
+ try {
+ parser.parse(inputSource, new StartHandler(locationHandler, dtdMappings));
+ } catch (Exception ex) {
+ throw new XWorkException(ex);
+ }
+
+ return builder.getDocument();
+ }
+
+ /**
+ * The <code>DOMBuilder</code> is a utility class that will generate a W3C
+ * DOM Document from SAX events.
+ *
+ * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
+ */
+ static public class DOMBuilder implements ContentHandler {
+
+ /** The default transformer factory shared by all instances */
+ protected static SAXTransformerFactory FACTORY;
+
+ /** The transformer factory */
+ protected SAXTransformerFactory factory;
+
+ /** The result */
+ protected DOMResult result;
+
+ /** The parentNode */
+ protected Node parentNode;
+
+ protected ContentHandler nextHandler;
+
+ static {
+ String parserProp = System.getProperty("xwork.saxTransformerFactory");
+ if (parserProp != null) {
+ try {
+ Class clazz = ObjectFactory.getObjectFactory().getClassInstance(parserProp);
+ FACTORY = (SAXTransformerFactory) clazz.newInstance();
+ }
+ catch (ClassNotFoundException e) {
+ LOG.error("Unable to load SAXTransformerFactory set by system property 'xwork.saxTransformerFactory': " + parserProp, e);
+ }
+ catch (Exception e) {
+ LOG.error("Unable to load SAXTransformerFactory set by system property 'xwork.saxTransformerFactory': " + parserProp, e);
+ }
+ }
+
+ if (FACTORY == null) {
+ FACTORY = (SAXTransformerFactory) TransformerFactory.newInstance();
+ }
+ }
+
+ /**
+ * Construct a new instance of this DOMBuilder.
+ */
+ public DOMBuilder() {
+ this((Node) null);
+ }
+
+ /**
+ * Construct a new instance of this DOMBuilder.
+ */
+ public DOMBuilder(SAXTransformerFactory factory) {
+ this(factory, null);
+ }
+
+ /**
+ * Constructs a new instance that appends nodes to the given parent node.
+ */
+ public DOMBuilder(Node parentNode) {
+ this(null, parentNode);
+ }
+
+ /**
+ * Construct a new instance of this DOMBuilder.
+ */
+ public DOMBuilder(SAXTransformerFactory factory, Node parentNode) {
+ this.factory = factory == null? FACTORY: factory;
+ this.parentNode = parentNode;
+ setup();
+ }
+
+ /**
+ * Setup this instance transformer and result objects.
+ */
+ private void setup() {
+ try {
+ TransformerHandler handler = this.factory.newTransformerHandler();
+ nextHandler = handler;
+ if (this.parentNode != null) {
+ this.result = new DOMResult(this.parentNode);
+ } else {
+ this.result = new DOMResult();
+ }
+ handler.setResult(this.result);
+ } catch (javax.xml.transform.TransformerException local) {
+ throw new XWorkException("Fatal-Error: Unable to get transformer handler", local);
+ }
+ }
+
+ /**
+ * Return the newly built Document.
+ */
+ public Document getDocument() {
+ if (this.result == null || this.result.getNode() == null) {
+ return null;
+ } else if (this.result.getNode().getNodeType() == Node.DOCUMENT_NODE) {
+ return (Document) this.result.getNode();
+ } else {
+ return this.result.getNode().getOwnerDocument();
+ }
+ }
+
+ public void setDocumentLocator(Locator locator) {
+ nextHandler.setDocumentLocator(locator);
+ }
+
+ public void startDocument() throws SAXException {
+ nextHandler.startDocument();
+ }
+
+ public void endDocument() throws SAXException {
+ nextHandler.endDocument();
+ }
+
+ public void startElement(String uri, String loc, String raw, Attributes attrs) throws SAXException {
+ nextHandler.startElement(uri, loc, raw, attrs);
+ }
+
+ public void endElement(String arg0, String arg1, String arg2) throws SAXException {
+ nextHandler.endElement(arg0, arg1, arg2);
+ }
+
+ public void startPrefixMapping(String arg0, String arg1) throws SAXException {
+ nextHandler.startPrefixMapping(arg0, arg1);
+ }
+
+ public void endPrefixMapping(String arg0) throws SAXException {
+ nextHandler.endPrefixMapping(arg0);
+ }
+
+ public void characters(char[] arg0, int arg1, int arg2) throws SAXException {
+ nextHandler.characters(arg0, arg1, arg2);
+ }
+
+ public void ignorableWhitespace(char[] arg0, int arg1, int arg2) throws SAXException {
+ nextHandler.ignorableWhitespace(arg0, arg1, arg2);
+ }
+
+ public void processingInstruction(String arg0, String arg1) throws SAXException {
+ nextHandler.processingInstruction(arg0, arg1);
+ }
+
+ public void skippedEntity(String arg0) throws SAXException {
+ nextHandler.skippedEntity(arg0);
+ }
+ }
+
+ public static class StartHandler extends DefaultHandler {
+
+ private ContentHandler nextHandler;
+ private Map<String, String> dtdMappings;
+
+ /**
+ * Create a filter that is chained to another handler.
+ * @param next the next handler in the chain.
+ */
+ public StartHandler(ContentHandler next, Map<String, String> dtdMappings) {
+ nextHandler = next;
+ this.dtdMappings = dtdMappings;
+ }
+
+ @Override
+ public void setDocumentLocator(Locator locator) {
+ nextHandler.setDocumentLocator(locator);
+ }
+
+ @Override
+ public void startDocument() throws SAXException {
+ nextHandler.startDocument();
+ }
+
+ @Override
+ public void endDocument() throws SAXException {
+ nextHandler.endDocument();
+ }
+
+ @Override
+ public void startElement(String uri, String loc, String raw, Attributes attrs) throws SAXException {
+ nextHandler.startElement(uri, loc, raw, attrs);
+ }
+
+ @Override
+ public void endElement(String arg0, String arg1, String arg2) throws SAXException {
+ nextHandler.endElement(arg0, arg1, arg2);
+ }
+
+ @Override
+ public void startPrefixMapping(String arg0, String arg1) throws SAXException {
+ nextHandler.startPrefixMapping(arg0, arg1);
+ }
+
+ @Override
+ public void endPrefixMapping(String arg0) throws SAXException {
+ nextHandler.endPrefixMapping(arg0);
+ }
+
+ @Override
+ public void characters(char[] arg0, int arg1, int arg2) throws SAXException {
+ nextHandler.characters(arg0, arg1, arg2);
+ }
+
+ @Override
+ public void ignorableWhitespace(char[] arg0, int arg1, int arg2) throws SAXException {
+ nextHandler.ignorableWhitespace(arg0, arg1, arg2);
+ }
+
+ @Override
+ public void processingInstruction(String arg0, String arg1) throws SAXException {
+ nextHandler.processingInstruction(arg0, arg1);
+ }
+
+ @Override
+ public void skippedEntity(String arg0) throws SAXException {
+ nextHandler.skippedEntity(arg0);
+ }
+
+ @Override
+ public InputSource resolveEntity(String publicId, String systemId) {
+ if (dtdMappings != null && dtdMappings.containsKey(publicId)) {
+ String val = dtdMappings.get(publicId).toString();
+ return new InputSource(ClassLoaderUtil.getResourceAsStream(val, DomHelper.class));
+ }
+ return null;
+ }
+
+ @Override
+ public void warning(SAXParseException exception) {
+ }
+
+ @Override
+ public void error(SAXParseException exception) throws SAXException {
+ LOG.error(exception.getMessage() + " at (" + exception.getPublicId() + ":" +
+ exception.getLineNumber() + ":" + exception.getColumnNumber() + ")", exception);
+ throw exception;
+ }
+
+ @Override
+ public void fatalError(SAXParseException exception) throws SAXException {
+ LOG.fatal(exception.getMessage() + " at (" + exception.getPublicId() + ":" +
+ exception.getLineNumber() + ":" + exception.getColumnNumber() + ")", exception);
+ throw exception;
+ }
+ }
+
+}