⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 beanwrapperimpl.java

📁 spring的源代码
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
						doTypeConversionIfNecessary(propertyName, propertyName, oldValue, newValue, null);
				map.put(key, convertedValue);
			}
			else {
				throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
						"Property referenced in indexed property path '" + propertyName +
						"' is neither an array nor a List nor a Map; returned value was [" + newValue + "]");
			}
		}

		else {
			PropertyDescriptor pd = getPropertyDescriptorInternal(propertyName);
			if (pd == null || pd.getWriteMethod() == null) {
				throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName);
			}

			Method readMethod = pd.getReadMethod();
			Method writeMethod = pd.getWriteMethod();
			Object oldValue = null;

			if (this.extractOldValueForEditor && readMethod != null) {
				if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
					readMethod.setAccessible(true);
				}
				try {
					oldValue = readMethod.invoke(this.object, new Object[0]);
				}
				catch (Exception ex) {
					if (logger.isDebugEnabled()) {
						logger.debug("Could not read previous value of property '" + this.nestedPath + propertyName + "'", ex);
					}
				}
			}

			try {
				Object convertedValue =
						doTypeConversionIfNecessary(propertyName, propertyName, oldValue, newValue, pd.getPropertyType());

				if (pd.getPropertyType().isPrimitive() && (convertedValue == null || "".equals(convertedValue))) {
					throw new IllegalArgumentException("Invalid value [" + newValue + "] for property '" +
							pd.getName() + "' of primitive type [" + pd.getPropertyType() + "]");
				}

				if (logger.isDebugEnabled()) {
					logger.debug("About to invoke write method [" + writeMethod + "] on object of class [" +
							this.object.getClass().getName() + "]");
				}
				if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
					writeMethod.setAccessible(true);
				}
				writeMethod.invoke(this.object, new Object[] {convertedValue});
				if (logger.isDebugEnabled()) {
					logger.debug("Invoked write method [" + writeMethod + "] with value of type [" +
							pd.getPropertyType().getName() + "]");
				}
			}
			catch (InvocationTargetException ex) {
				PropertyChangeEvent propertyChangeEvent =
						new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
				if (ex.getTargetException() instanceof ClassCastException) {
					throw new TypeMismatchException(propertyChangeEvent, pd.getPropertyType(), ex.getTargetException());
				}
				else {
					throw new MethodInvocationException(propertyChangeEvent, ex.getTargetException());
				}
			}
			catch (IllegalArgumentException ex) {
				PropertyChangeEvent pce =
						new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
				throw new TypeMismatchException(pce, pd.getPropertyType(), ex);
			}
			catch (IllegalAccessException ex) {
				PropertyChangeEvent pce =
						new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
				throw new MethodInvocationException(pce, ex);
			}
		}
	}

	public void setPropertyValue(PropertyValue pv) throws BeansException {
		setPropertyValue(pv.getName(), pv.getValue());
	}

	/**
	 * Bulk update from a Map.
	 * Bulk updates from PropertyValues are more powerful: this method is
	 * provided for convenience.
	 * @param map map containing properties to set, as name-value pairs.
	 * The map may include nested properties.
	 * @throws BeansException if there's a fatal, low-level exception
	 */
	public void setPropertyValues(Map map) throws BeansException {
		setPropertyValues(new MutablePropertyValues(map));
	}

	public void setPropertyValues(PropertyValues pvs) throws BeansException {
		setPropertyValues(pvs, false);
	}

	public void setPropertyValues(PropertyValues propertyValues, boolean ignoreUnknown) throws BeansException {
		List propertyAccessExceptions = new ArrayList();
		PropertyValue[] pvs = propertyValues.getPropertyValues();
		for (int i = 0; i < pvs.length; i++) {
			try {
				// This method may throw any BeansException, which won't be caught
				// here, if there is a critical failure such as no matching field.
				// We can attempt to deal only with less serious exceptions.
				setPropertyValue(pvs[i]);
			}
			catch (NotWritablePropertyException ex) {
				if (!ignoreUnknown) {
					throw ex;
				}
				// Otherwise, just ignore it and continue...
			}
			catch (PropertyAccessException ex) {
				propertyAccessExceptions.add(ex);
			}
		}

		// If we encountered individual exceptions, throw the composite exception.
		if (!propertyAccessExceptions.isEmpty()) {
			Object[] paeArray =
					propertyAccessExceptions.toArray(new PropertyAccessException[propertyAccessExceptions.size()]);
			throw new PropertyAccessExceptionsException(this, (PropertyAccessException[]) paeArray);
		}
	}

	private PropertyChangeEvent createPropertyChangeEvent(String propertyName, Object oldValue, Object newValue) {
		return new PropertyChangeEvent((this.rootObject != null ? this.rootObject : "constructor"),
				(propertyName != null ? this.nestedPath + propertyName : null),
				oldValue, newValue);
	}

	/**
	 * Convert the value to the required type (if necessary from a String).
	 * <p>Conversions from String to any type use the <code>setAsText</code> method
	 * of the PropertyEditor class. Note that a PropertyEditor must be registered
	 * for the given class for this to work; this is a standard JavaBeans API.
	 * A number of PropertyEditors are automatically registered by BeanWrapperImpl.
	 * @param newValue proposed change value
	 * @param requiredType the type we must convert to
	 * @return the new value, possibly the result of type conversion
	 * @throws TypeMismatchException if type conversion failed
	 * @see java.beans.PropertyEditor#setAsText(String)
	 * @see java.beans.PropertyEditor#getValue()
	 */
	public Object doTypeConversionIfNecessary(Object newValue, Class requiredType) throws TypeMismatchException {
		return doTypeConversionIfNecessary(null, null, null, newValue, requiredType);
	}

	/**
	 * Convert the value to the required type (if necessary from a String),
	 * for the specified property.
	 * @param propertyName name of the property
	 * @param oldValue previous value, if available (may be <code>null</code>)
	 * @param newValue proposed change value
	 * @param requiredType the type we must convert to
	 * (or <code>null</code> if not known, for example in case of a collection element)
	 * @return the new value, possibly the result of type conversion
	 * @throws TypeMismatchException if type conversion failed
	 */
	protected Object doTypeConversionIfNecessary(String propertyName, String fullPropertyName,
			Object oldValue, Object newValue, Class requiredType) throws TypeMismatchException {

		Object convertedValue = newValue;

		// Custom editor for this type?
		PropertyEditor pe = findCustomEditor(requiredType, fullPropertyName);

		// Value not of required type?
		if (pe != null ||
				(requiredType != null &&
				(requiredType.isArray() || !requiredType.isInstance(convertedValue)))) {

			if (requiredType != null) {
				if (pe == null) {
					// No custom editor -> check BeanWrapperImpl's default editors.
					pe = (PropertyEditor) getDefaultEditor(requiredType);
					if (pe == null) {
						// No BeanWrapper default editor -> check standard JavaBean editors.
						pe = PropertyEditorManager.findEditor(requiredType);
					}
				}
			}

			if (pe != null && !(convertedValue instanceof String)) {
				// Not a String -> use PropertyEditor's setValue.
				// With standard PropertyEditors, this will return the very same object;
				// we just want to allow special PropertyEditors to override setValue
				// for type conversion from non-String values to the required type.
				try {
					pe.setValue(convertedValue);
					Object newConvertedValue = pe.getValue();
					if (newConvertedValue != convertedValue) {
						convertedValue = newConvertedValue;
						// Reset PropertyEditor: It already did a proper conversion.
						// Don't use it again for a setAsText call.
						pe = null;
					}
				}
				catch (IllegalArgumentException ex) {
					throw new TypeMismatchException(
							createPropertyChangeEvent(fullPropertyName, oldValue, newValue), requiredType, ex);
				}
			}

			if (requiredType != null && !requiredType.isArray() && convertedValue instanceof String[]) {
				// Convert String array to a comma-separated String.
				// Only applies if no PropertyEditor converted the String array before.
				// The CSV String will be passed into a PropertyEditor's setAsText method, if any.
				if (logger.isDebugEnabled()) {
					logger.debug("Converting String array to comma-delimited String [" + convertedValue + "]");
				}
				convertedValue = StringUtils.arrayToCommaDelimitedString((String[]) convertedValue);
			}

			if (pe != null && convertedValue instanceof String) {
				// Use PropertyEditor's setAsText in case of a String value.
				if (logger.isDebugEnabled()) {
					logger.debug("Converting String to [" + requiredType + "] using property editor [" + pe + "]");
				}
				try {
					pe.setValue(oldValue);
					pe.setAsText((String) convertedValue);
					convertedValue = pe.getValue();
				}
				catch (IllegalArgumentException ex) {
					throw new TypeMismatchException(
							createPropertyChangeEvent(fullPropertyName, oldValue, newValue), requiredType, ex);
				}
			}

			if (requiredType != null) {
				// Array required -> apply appropriate conversion of elements.
				if (requiredType.isArray()) {
					Class componentType = requiredType.getComponentType();
					if (convertedValue instanceof Collection) {
						// Convert Collection elements to array elements.
						Collection coll = (Collection) convertedValue;
						Object result = Array.newInstance(componentType, coll.size());
						int i = 0;
						for (Iterator it = coll.iterator(); it.hasNext(); i++) {
							Object value = doTypeConversionIfNecessary(
									propertyName, propertyName + PROPERTY_KEY_PREFIX + i + PROPERTY_KEY_SUFFIX,
									null, it.next(), componentType);
							Array.set(result, i, value);
						}
						return result;
					}
					else if (convertedValue != null && convertedValue.getClass().isArray()) {
						// Convert Collection elements to array elements.
						int arrayLength = Array.getLength(convertedValue);
						Object result = Array.newInstance(componentType, arrayLength);
						for (int i = 0; i < arrayLength; i++) {
							Object value = doTypeConversionIfNecessary(
									propertyName, propertyName + PROPERTY_KEY_PREFIX + i + PROPERTY_KEY_SUFFIX,
									null, Array.get(convertedValue, i), componentType);
							Array.set(result, i, value);
						}
						return result;
					}
					else {
						// A plain value: convert it to an array with a single component.
						Object result = Array.newInstance(componentType, 1);
						Object value = doTypeConversionIfNecessary(
								propertyName, propertyName + PROPERTY_KEY_PREFIX + 0 + PROPERTY_KEY_SUFFIX,
								null, convertedValue, componentType);
						Array.set(result, 0, value);
						return result;
					}
				}

				// If the resulting value definitely doesn't match the required type,
				// try field lookup as fallback. If no matching field found,
				// throw explicit TypeMismatchException with full context information.
				if (convertedValue != null && !requiredType.isPrimitive() &&
						!requiredType.isInstance(convertedValue)) {

					// In case of String value, try to find matching field (for JDK 1.5
					// enum or custom enum with values defined as static fields).
					if (convertedValue instanceof String) {
						try {
							Field enumField = requiredType.getField((String) convertedValue);
							return enumField.get(null);
						}
						catch (Exception ex) {
							if (logger.isDebugEnabled()) {
								logger.debug("Field [" + convertedValue + "] isn't an enum value", ex);
							}
						}
					}

					// Definitely doesn't match: throw TypeMismatchException.
					throw new TypeMismatchException(
							createPropertyChangeEvent(fullPropertyName, oldValue, newValue), requiredType);
				}
			}
		}

		return convertedValue;
	}


	public String toString() {
		StringBuffer sb = new StringBuffer("BeanWrapperImpl: wrapping class [");
		sb.append(getWrappedClass().getName()).append("]");
		return sb.toString();
	}


	//---------------------------------------------------------------------
	// Inner class for internal use
	//---------------------------------------------------------------------

	private static class PropertyTokenHolder {

		private String canonicalName;

		private String actualName;

		private String[] keys;
	}

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -