| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package com.opensymphony.xwork2.ognl.accessor; |
| |
| import com.opensymphony.xwork2.ObjectFactory; |
| import com.opensymphony.xwork2.conversion.ObjectTypeDeterminer; |
| import com.opensymphony.xwork2.conversion.impl.XWorkConverter; |
| import com.opensymphony.xwork2.inject.Inject; |
| import com.opensymphony.xwork2.ognl.OgnlUtil; |
| import com.opensymphony.xwork2.util.reflection.ReflectionContextState; |
| import ognl.ListPropertyAccessor; |
| import ognl.OgnlException; |
| import ognl.PropertyAccessor; |
| import org.apache.struts2.StrutsConstants; |
| import org.apache.struts2.StrutsException; |
| |
| import java.util.Collection; |
| import java.util.List; |
| import java.util.Map; |
| |
| /** |
| * Overrides the list property accessor so in the case of trying |
| * to add properties of a given bean and the JavaBean is not present, |
| * this class will create the necessary blank JavaBeans. |
| * |
| * @author Gabriel Zimmerman |
| */ |
| public class XWorkListPropertyAccessor extends ListPropertyAccessor { |
| |
| private XWorkCollectionPropertyAccessor _sAcc = new XWorkCollectionPropertyAccessor(); |
| |
| private XWorkConverter xworkConverter; |
| private ObjectFactory objectFactory; |
| private ObjectTypeDeterminer objectTypeDeterminer; |
| private OgnlUtil ognlUtil; |
| private int autoGrowCollectionLimit = 255; |
| |
| @Deprecated() |
| @Inject(value = "xwork.autoGrowCollectionLimit", required = false) |
| public void setDeprecatedAutoGrowCollectionLimit(String value) { |
| this.autoGrowCollectionLimit = Integer.valueOf(value); |
| } |
| |
| @Inject(value = StrutsConstants.STRUTS_OGNL_AUTO_GROWTH_COLLECTION_LIMIT, required = false) |
| public void setAutoGrowCollectionLimit(String value) { |
| this.autoGrowCollectionLimit = Integer.parseInt(value); |
| } |
| |
| @Inject("java.util.Collection") |
| public void setXWorkCollectionPropertyAccessor(PropertyAccessor acc) { |
| this._sAcc = (XWorkCollectionPropertyAccessor) acc; |
| } |
| |
| @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; |
| } |
| |
| @Inject |
| public void setOgnlUtil(OgnlUtil util) { |
| this.ognlUtil = util; |
| } |
| |
| @Override |
| public Object getProperty(Map context, Object target, Object name) throws OgnlException { |
| |
| if (ReflectionContextState.isGettingByKeyProperty(context) |
| || name.equals(XWorkCollectionPropertyAccessor.KEY_PROPERTY_FOR_CREATION)) { |
| return _sAcc.getProperty(context, target, name); |
| } else if (name instanceof String) { |
| return super.getProperty(context, target, name); |
| } |
| ReflectionContextState.updateCurrentPropertyPath(context, name); |
| Class lastClass = (Class) context.get(XWorkConverter.LAST_BEAN_CLASS_ACCESSED); |
| String lastProperty = (String) context.get(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED); |
| |
| if (name instanceof Number |
| && ReflectionContextState.isCreatingNullObjects(context) |
| && objectTypeDeterminer.shouldCreateIfNew(lastClass,lastProperty,target,null,true)) { |
| |
| List list = (List) target; |
| int index = ((Number) name).intValue(); |
| int listSize = list.size(); |
| |
| if (lastClass == null || lastProperty == null) { |
| return super.getProperty(context, target, name); |
| } |
| Class beanClass = objectTypeDeterminer.getElementClass(lastClass, lastProperty, name); |
| if (listSize <= index) { |
| Object result; |
| |
| for (int i = listSize; i < index; i++) { |
| list.add(null); |
| } |
| try { |
| list.add(index, result = objectFactory.buildBean(beanClass, context)); |
| } catch (Exception exc) { |
| throw new StrutsException(exc); |
| } |
| return result; |
| } else if (list.get(index) == null) { |
| Object result; |
| try { |
| list.set(index, result = objectFactory.buildBean(beanClass, context)); |
| } catch (Exception exc) { |
| throw new StrutsException(exc); |
| } |
| return result; |
| } |
| } |
| return super.getProperty(context, target, name); |
| } |
| |
| @Override |
| public void setProperty(Map context, Object target, Object name, Object value) |
| throws OgnlException { |
| |
| Class lastClass = (Class) context.get(XWorkConverter.LAST_BEAN_CLASS_ACCESSED); |
| String lastProperty = (String) context.get(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED); |
| Class convertToClass = objectTypeDeterminer.getElementClass(lastClass, lastProperty, name); |
| |
| if (name instanceof String && value.getClass().isArray()) { |
| // looks like the input game in the form of "someList.foo" and |
| // we are expected to define the index values ourselves. |
| // So let's do it: |
| |
| Collection c = (Collection) target; |
| Object[] values = (Object[]) value; |
| for (Object v : values) { |
| try { |
| Object o = objectFactory.buildBean(convertToClass, context); |
| ognlUtil.setValue((String) name, context, o, v); |
| c.add(o); |
| } catch (Exception e) { |
| throw new OgnlException("Error converting given String values for Collection.", e); |
| } |
| } |
| |
| // we don't want to do the normal list property setting now, since we've already done the work |
| // just return instead |
| return; |
| } |
| |
| Object realValue = getRealValue(context, value, convertToClass); |
| |
| if (target instanceof List && name instanceof Number) { |
| //make sure there are enough spaces in the List to set |
| List list = (List) target; |
| int listSize = list.size(); |
| int count = ((Number) name).intValue(); |
| if(count > autoGrowCollectionLimit) |
| throw new OgnlException("Error auto growing collection size to " + count + " which limited to " |
| + autoGrowCollectionLimit); |
| if (count >= listSize) { |
| for (int i = listSize; i <= count; i++) { |
| list.add(null); |
| } |
| } |
| } |
| |
| super.setProperty(context, target, name, realValue); |
| } |
| |
| private Object getRealValue(Map context, Object value, Class convertToClass) { |
| if (value == null || convertToClass == null) { |
| return value; |
| } |
| return xworkConverter.convertValue(context, value, convertToClass); |
| } |
| } |