All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.opensymphony.xwork2.conversion.impl.InstantiatingNullHandler Maven / Gradle / Ivy

There is a newer version: 6.4.0
Show newest version
/*
 * 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.conversion.impl;

import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.conversion.NullHandler;
import com.opensymphony.xwork2.conversion.ObjectTypeDeterminer;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
import com.opensymphony.xwork2.util.reflection.ReflectionProvider;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.beans.PropertyDescriptor;
import java.util.*;


/**
 * 
 * 

* Provided that the key {@link ReflectionContextState#CREATE_NULL_OBJECTS} is in the action context with a value of true (this key is set * only during the execution of the {@link com.opensymphony.xwork2.interceptor.ParametersInterceptor}), OGNL expressions * that have caused a NullPointerException will be temporarily stopped for evaluation while the system automatically * tries to solve the null references by automatically creating the object. *

* *

The following rules are used when handling null references:

* *
    *
  • If the property is declared exactly as a {@link Collection} or {@link List}, then an ArrayList shall be * returned and assigned to the null references.
  • *
  • If the property is declared as a {@link Map}, then a HashMap will be returned and assigned to the null * references.
  • *
  • If the null property is a simple bean with a no-arg constructor, it will simply be created using the {@link * ObjectFactory#buildBean(java.lang.Class, java.util.Map)} method.
  • *
* * * * *

* For example, if a form element has a text field named person.name and the expression person evaluates * to null, then this class will be invoked. Because the person expression evaluates to a Person class, a * new Person is created and assigned to the null reference. Finally, the name is set on that object and the overall * effect is that the system automatically created a Person object for you, set it by calling setUsers() and then * finally called getUsers().setName() as you would typically expect. *

* * * @author Matt Ho * @author Patrick Lightbody */ public class InstantiatingNullHandler implements NullHandler { private static final Logger LOG = LogManager.getLogger(InstantiatingNullHandler.class); private ReflectionProvider reflectionProvider; private ObjectFactory objectFactory; private ObjectTypeDeterminer objectTypeDeterminer; @Inject public void setObjectTypeDeterminer(ObjectTypeDeterminer det) { this.objectTypeDeterminer = det; } @Inject public void setReflectionProvider(ReflectionProvider prov) { this.reflectionProvider = prov; } @Inject public void setObjectFactory(ObjectFactory fac) { this.objectFactory = fac; } public Object nullMethodResult(Map context, Object target, String methodName, Object[] args) { LOG.debug("Entering nullMethodResult"); return null; } public Object nullPropertyValue(Map context, Object target, Object property) { LOG.debug("Entering nullPropertyValue [target={}, property={}]", target, property); boolean c = ReflectionContextState.isCreatingNullObjects(context); if (!c) { return null; } if ((target == null) || (property == null)) { return null; } try { String propName = property.toString(); Object realTarget = reflectionProvider.getRealTarget(propName, context, target); Class clazz = null; if (realTarget != null) { PropertyDescriptor pd = reflectionProvider.getPropertyDescriptor(realTarget.getClass(), propName); if (pd == null) { return null; } clazz = pd.getPropertyType(); } if (clazz == null) { // can't do much here! return null; } Object param = createObject(clazz, realTarget, propName, context); reflectionProvider.setValue(propName, context, realTarget, param); return param; } catch (Exception e) { LOG.error("Could not create and/or set value back on to object", e); } return null; } private Object createObject(Class clazz, Object target, String property, Map context) throws Exception { if (Set.class.isAssignableFrom(clazz)) { return new HashSet(); } else if (Collection.class.isAssignableFrom(clazz)) { return new ArrayList(); } else if (clazz == Map.class) { return new HashMap(); } else if (clazz == EnumMap.class) { Class keyClass = objectTypeDeterminer.getKeyClass(target.getClass(), property); return new EnumMap(keyClass); } return objectFactory.buildBean(clazz, context); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy