Example #1
1
 private Object newValue(Class<?> type, String name) {
   try {
     if (type.isArray()) {
       Class<?> componentType = type.getComponentType();
       // TODO - only handles 2-dimensional arrays
       if (componentType.isArray()) {
         Object array = Array.newInstance(componentType, 1);
         Array.set(array, 0, Array.newInstance(componentType.getComponentType(), 0));
         return array;
       } else {
         return Array.newInstance(componentType, 0);
       }
     } else if (Collection.class.isAssignableFrom(type)) {
       return CollectionFactory.createCollection(type, 16);
     } else if (Map.class.isAssignableFrom(type)) {
       return CollectionFactory.createMap(type, 16);
     } else {
       return type.newInstance();
     }
   } catch (Exception ex) {
     // TODO Root cause exception context is lost here... should we throw another exception type
     // that preserves context instead?
     throw new NullValueInNestedPathException(
         getRootClass(),
         this.nestedPath + name,
         "Could not instantiate property type ["
             + type.getName()
             + "] to auto-grow nested property path: "
             + ex);
   }
 }
Example #2
0
  /**
   * 将对象中的属性值置入到fields中。
   *
   * <p>对于<code>isValidated()</code>为<code>true</code>的group,该方法无效。
   */
  public void mapTo(Object object) {
    if (isValidated() || object == null) {
      return;
    }

    if (log.isDebugEnabled()) {
      log.debug(
          "Mapping properties to fields: group=\"{}\", object={}",
          getName(),
          ObjectUtil.identityToString(object));
    }

    BeanWrapper bean = new BeanWrapperImpl(object);
    getForm().getFormConfig().getPropertyEditorRegistrar().registerCustomEditors(bean);

    for (Field field : getFields()) {
      String propertyName = field.getFieldConfig().getPropertyName();

      if (bean.isReadableProperty(propertyName)) {
        Object propertyValue = bean.getPropertyValue(propertyName);
        Class<?> propertyType = bean.getPropertyType(propertyName);
        PropertyEditor editor = bean.findCustomEditor(propertyType, propertyName);

        if (editor == null) {
          editor = BeanUtils.findEditorByConvention(propertyType);
        }

        if (editor == null) {
          if (propertyType.isArray()
              || CollectionFactory.isApproximableCollectionType(propertyType)) {
            field.setValues((String[]) bean.convertIfNecessary(propertyValue, String[].class));
          } else {
            field.setValue(bean.convertIfNecessary(propertyValue, String.class));
          }
        } else {
          editor.setValue(propertyValue);
          field.setValue(editor.getAsText());
        }
      } else {
        log.debug(
            "No readable property \"{}\" found in type {}",
            propertyName,
            object.getClass().getName());
      }
    }
  }
  /**
   * Reads the given {@link DBObject} into a {@link Map}. will recursively resolve nested {@link
   * Map}s as well.
   *
   * @param type the {@link Map} {@link TypeInformation} to be used to unmarshall this {@link
   *     DBObject}.
   * @param dbObject must not be {@literal null}
   * @param path must not be {@literal null}
   * @return
   */
  @SuppressWarnings("unchecked")
  protected Map<Object, Object> readMap(
      TypeInformation<?> type, DBObject dbObject, ObjectPath path) {

    Assert.notNull(dbObject, "DBObject must not be null!");
    Assert.notNull(path, "Object path must not be null!");

    Class<?> mapType = typeMapper.readType(dbObject, type).getType();

    TypeInformation<?> keyType = type.getComponentType();
    Class<?> rawKeyType = keyType == null ? null : keyType.getType();

    TypeInformation<?> valueType = type.getMapValueType();
    Class<?> rawValueType = valueType == null ? null : valueType.getType();

    Map<Object, Object> map =
        CollectionFactory.createMap(mapType, rawKeyType, dbObject.keySet().size());
    Map<String, Object> sourceMap = dbObject.toMap();

    for (Entry<String, Object> entry : sourceMap.entrySet()) {
      if (typeMapper.isTypeKey(entry.getKey())) {
        continue;
      }

      Object key = potentiallyUnescapeMapKey(entry.getKey());

      if (rawKeyType != null) {
        key = conversionService.convert(key, rawKeyType);
      }

      Object value = entry.getValue();

      if (value instanceof DBObject) {
        map.put(key, read(valueType, (DBObject) value, path));
      } else if (value instanceof DBRef) {
        map.put(
            key,
            DBRef.class.equals(rawValueType) ? value : read(valueType, readRef((DBRef) value)));
      } else {
        Class<?> valueClass = valueType == null ? null : valueType.getType();
        map.put(key, getPotentiallyConvertedSimpleRead(value, valueClass));
      }
    }

    return map;
  }
  /**
   * Reads the given {@link BasicDBList} into a collection of the given {@link TypeInformation}.
   *
   * @param targetType must not be {@literal null}.
   * @param sourceValue must not be {@literal null}.
   * @param path must not be {@literal null}.
   * @return the converted {@link Collection} or array, will never be {@literal null}.
   */
  private Object readCollectionOrArray(
      TypeInformation<?> targetType, BasicDBList sourceValue, ObjectPath path) {

    Assert.notNull(targetType, "Target type must not be null!");
    Assert.notNull(path, "Object path must not be null!");

    Class<?> collectionType = targetType.getType();

    if (sourceValue.isEmpty()) {
      return getPotentiallyConvertedSimpleRead(new HashSet<Object>(), collectionType);
    }

    TypeInformation<?> componentType = targetType.getComponentType();
    Class<?> rawComponentType = componentType == null ? null : componentType.getType();

    collectionType =
        Collection.class.isAssignableFrom(collectionType) ? collectionType : List.class;
    Collection<Object> items =
        targetType.getType().isArray()
            ? new ArrayList<Object>()
            : CollectionFactory.createCollection(
                collectionType, rawComponentType, sourceValue.size());

    for (int i = 0; i < sourceValue.size(); i++) {

      Object dbObjItem = sourceValue.get(i);

      if (dbObjItem instanceof DBRef) {
        items.add(
            DBRef.class.equals(rawComponentType)
                ? dbObjItem
                : read(componentType, readRef((DBRef) dbObjItem), path));
      } else if (dbObjItem instanceof DBObject) {
        items.add(read(componentType, (DBObject) dbObjItem, path));
      } else {
        items.add(getPotentiallyConvertedSimpleRead(dbObjItem, rawComponentType));
      }
    }

    return getPotentiallyConvertedSimpleRead(items, targetType.getType());
  }
  public Map getBeansOfType(Class type, boolean includePrototypes, boolean includeFactoryBeans)
      throws BeansException {

    String[] beanNames = getBeanNamesForType(type, includePrototypes, includeFactoryBeans);
    Map result = CollectionFactory.createLinkedMapIfPossible(beanNames.length);
    for (int i = 0; i < beanNames.length; i++) {
      String beanName = beanNames[i];
      try {
        result.put(beanName, getBean(beanName));
      } catch (BeanCreationException ex) {
        if (ex.contains(BeanCurrentlyInCreationException.class)) {
          if (logger.isDebugEnabled()) {
            logger.debug("Ignoring match to currently created bean '" + beanName + "'", ex);
          }
          // Ignore: indicates a circular reference when autowiring constructors.
          // We want to find matches other than the currently created bean itself.
        } else {
          throw ex;
        }
      }
    }
    return result;
  }
 @Override
 public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
   if (source == null) {
     return null;
   }
   String string = (String) source;
   String[] fields = StringUtils.commaDelimitedListToStringArray(string);
   Collection<Object> target =
       CollectionFactory.createCollection(targetType.getType(), fields.length);
   if (targetType.getElementTypeDescriptor() == null) {
     for (String field : fields) {
       target.add(field.trim());
     }
   } else {
     for (String field : fields) {
       Object targetElement =
           this.conversionService.convert(
               field.trim(), sourceType, targetType.getElementTypeDescriptor());
       target.add(targetElement);
     }
   }
   return target;
 }
/** @author diogomariano */
public class CpfHttpServletRequest implements HttpServletRequest {

  public static final String DEFAULT_PROTOCOL = "http";
  public static final String DEFAULT_SERVER_ADDR = "127.0.0.1";
  public static final String DEFAULT_SERVER_NAME = "localhost";
  public static final int DEFAULT_SERVER_PORT = 8080;
  public static final String DEFAULT_REMOTE_ADDR = "127.0.0.1";
  public static final String DEFAULT_REMOTE_HOST = "localhost";

  private String protocol = DEFAULT_PROTOCOL;
  private String scheme = DEFAULT_PROTOCOL;
  private String serverName = DEFAULT_SERVER_NAME;
  private int serverPort = DEFAULT_SERVER_PORT;
  private int localPort = DEFAULT_SERVER_PORT;
  private boolean secure = false;
  private int remotePort = DEFAULT_SERVER_PORT;
  private String localName = DEFAULT_SERVER_NAME;
  private String localAddr = DEFAULT_SERVER_ADDR;
  private String remoteAddr = DEFAULT_REMOTE_ADDR;
  private String remoteHost = DEFAULT_REMOTE_HOST;

  private final ServletContext servletContext;
  private String method;
  private String pathInfo;
  private String requestURI;
  private String contextPath = "";
  private final Vector locales = new Vector();

  private String authType;
  private Cookie[] cookies;
  private final Hashtable headers = new Hashtable();
  private final Hashtable attributes = new Hashtable();

  private final Map parameters = CollectionFactory.createLinkedMapIfPossible(16);

  private final Set userRoles = new HashSet();

  private boolean active = true;
  private String servletPath;
  private Principal userPrincipal;
  private String queryString;
  private String remoteUser;

  private HttpSession session;

  private boolean requestedSessionIdValid = true;
  private boolean requestedSessionIdFromCookie = true;
  private boolean requestedSessionIdFromURL = false;
  private String characterEncoding;

  private byte[] content;
  private String contentType;

  public CpfHttpServletRequest() {
    this(null, "", "");
  }

  public CpfHttpServletRequest(String method, String requestURI) {
    this(null, method, requestURI);
  }

  public CpfHttpServletRequest(ServletContext servletContext) {
    this(servletContext, "", "");
  }

  public CpfHttpServletRequest(ServletContext servletContext, String method, String requestURI) {
    this.servletContext = (servletContext != null ? servletContext : new CpfServletContext());
    this.method = method;
    this.requestURI = requestURI;
    this.locales.add(Locale.ENGLISH);
  }

  public boolean isActive() {
    return this.active;
  }

  public void close() {
    this.active = false;
  }

  public void invalidate() {
    close();
    clearAttributes();
  }

  protected void checkActive() throws IllegalStateException {
    if (!this.active) {
      throw new IllegalStateException("Request is not active anymore");
    }
  }

  @Override
  public String getAuthType() {
    return this.authType;
  }

  public void setAuthType(String authType) {
    this.authType = authType;
  }

  @Override
  public Cookie[] getCookies() {
    return this.cookies;
  }

  public void setCookies(Cookie[] cookies) {
    this.cookies = cookies;
  }

  public void addHeader(String name, Object value) {
    HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name);
    if (header == null) {
      header = new HeaderValueHolder();
      this.headers.put(name, header);
    }
    if (value instanceof Collection) {
      header.addValues((Collection) value);
    } else if (value.getClass().isArray()) {
      header.addValueArray(value);
    } else {
      header.addValue(value);
    }
  }

  @Override
  public long getDateHeader(String name) {
    HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name);
    Object value = (header != null ? header.getValue() : null);
    if (value instanceof Date) {
      return ((Date) value).getTime();
    } else if (value instanceof Number) {
      return ((Number) value).longValue();
    } else if (value != null) {
      throw new IllegalArgumentException(
          "Value for header '" + name + "' is neither a Date nor a Number: " + value);
    } else {
      return -1L;
    }
  }

  @Override
  public String getHeader(String name) {
    HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name);
    return (header != null ? header.getValue().toString() : null);
  }

  @Override
  public Enumeration getHeaders(String name) {
    HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name);
    return Collections.enumeration(header != null ? header.getValues() : Collections.EMPTY_LIST);
  }

  @Override
  public Enumeration getHeaderNames() {
    return this.headers.keys();
  }

  @Override
  public int getIntHeader(String name) {
    HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name);
    Object value = (header != null ? header.getValue() : null);
    if (value instanceof Number) {
      return ((Number) value).intValue();
    } else if (value instanceof String) {
      return Integer.parseInt((String) value);
    } else if (value != null) {
      throw new NumberFormatException("Value for header '" + name + "' is not a Number: " + value);
    } else {
      return -1;
    }
  }

  @Override
  public String getMethod() {
    return this.method;
  }

  public void setMethod() {
    this.method = method;
  }

  @Override
  public String getPathInfo() {
    return this.pathInfo;
  }

  public void setPathInfo(String pathInfo) {
    this.pathInfo = pathInfo;
  }

  @Override
  public String getPathTranslated() {
    return (this.pathInfo != null ? getRealPath(this.pathInfo) : null);
  }

  @Override
  public String getContextPath() {
    return this.contextPath;
  }

  public void setContextPath(String contextPath) {
    this.contextPath = contextPath;
  }

  @Override
  public String getQueryString() {
    return this.queryString;
  }

  public void setQueryString(String queryString) {
    this.queryString = queryString;
  }

  @Override
  public String getRemoteUser() {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void setRemoteUser(String remoteUser) {
    this.remoteUser = remoteUser;
  }

  public void addRole(String role) {
    addUserRole(role);
  }

  public void addUserRole(String role) {
    this.userRoles.add(role);
  }

  @Override
  public boolean isUserInRole(String role) {
    return this.userRoles.contains(role);
  }

  @Override
  public Principal getUserPrincipal() {
    return this.userPrincipal;
  }

  public void setUserPrincipal(Principal userPrincipal) {
    this.userPrincipal = userPrincipal;
  }

  @Override
  public String getRequestedSessionId() {
    HttpSession session = getSession();
    return (session != null ? session.getId() : null);
  }

  @Override
  public String getRequestURI() {
    return this.requestURI;
  }

  public void setRequestURI(String requestURI) {
    this.requestURI = requestURI;
  }

  @Override
  public StringBuffer getRequestURL() {
    StringBuffer url = new StringBuffer(this.scheme);
    url.append("://").append(this.serverName).append(':').append(this.serverPort);
    url.append(getRequestURI());
    return url;
  }

  @Override
  public String getServletPath() {
    return this.servletPath;
  }

  public void setServletPath(String servletPath) {
    this.servletPath = servletPath;
  }

  @Override
  public HttpSession getSession(boolean create) {
    checkActive();
    // Reset session if invalidated.
    if (this.session instanceof CpfHttpSession && ((CpfHttpSession) this.session).isInvalid()) {
      this.session = null;
    }
    // Create new session if necessary.
    if (this.session == null && create) {
      this.session = new CpfHttpSession(this.servletContext);
    }
    return this.session;
  }

  @Override
  public HttpSession getSession() {
    return getSession(true);
  }

  public void setSession(HttpSession session) {
    this.session = session;
    if (session instanceof CpfHttpSession) {
      CpfHttpSession cpfSession = ((CpfHttpSession) session);
      cpfSession.access();
    }
  }

  @Override
  public boolean isRequestedSessionIdValid() {
    return this.requestedSessionIdValid;
  }

  public void setRequestedSessionIdValid(boolean requestedSessionIdValid) {
    this.requestedSessionIdValid = requestedSessionIdValid;
  }

  @Override
  public boolean isRequestedSessionIdFromCookie() {
    return this.requestedSessionIdFromCookie;
  }

  public void setRequestedSessionIdFromCookie(boolean requestedSessionIdFromCookie) {
    this.requestedSessionIdFromCookie = requestedSessionIdFromCookie;
  }

  @Override
  public boolean isRequestedSessionIdFromURL() {
    return this.requestedSessionIdFromURL;
  }

  public boolean isRequestedSessionIdFromUrl() {
    return isRequestedSessionIdFromURL();
  }

  public void setRequestedSessionIdFromURL(boolean requestedSessionIdFromURL) {
    this.requestedSessionIdFromURL = requestedSessionIdFromURL;
  }

  @Override
  public Object getAttribute(String name) {
    checkActive();
    return this.attributes.get(name);
  }

  @Override
  public Enumeration getAttributeNames() {
    return this.attributes.keys();
  }

  @Override
  public String getCharacterEncoding() {
    return this.characterEncoding;
  }

  @Override
  public void setCharacterEncoding(String characterEncoding) throws UnsupportedEncodingException {
    this.characterEncoding = characterEncoding;
  }

  public void setContent(byte[] content) {
    this.content = content;
  }

  @Override
  public int getContentLength() {
    return (this.content != null ? this.content.length : -1);
  }

  @Override
  public String getContentType() {
    return this.contentType;
  }

  public void setContentType(String contentType) {
    this.contentType = contentType;
  }

  @Override
  public ServletInputStream getInputStream() throws IOException {
    if (this.content != null) {
      return new DelegatingServletInputStream(new ByteArrayInputStream(this.content));
    } else {
      return null;
    }
  }

  @Override
  public String getParameter(String name) {
    String[] arr = (String[]) this.parameters.get(name);
    return (arr != null && arr.length > 0 ? arr[0] : null);
  }

  public void setParameter(String name, String value) {
    setParameter(name, new String[] {value});
  }

  public void setParameter(String name, String[] values) {
    this.parameters.put(name, values);
  }

  public void addParameter(String name, String value) {
    addParameter(name, new String[] {value});
  }

  public void addParameter(String name, String[] values) {
    String[] oldArr = (String[]) this.parameters.get(name);
    if (oldArr != null) {
      String[] newArr = new String[oldArr.length + values.length];
      System.arraycopy(oldArr, 0, newArr, 0, oldArr.length);
      System.arraycopy(values, 0, newArr, oldArr.length, values.length);
      this.parameters.put(name, newArr);
    } else {
      this.parameters.put(name, values);
    }
  }

  public void removeParameter(String name) {
    this.parameters.remove(name);
  }

  @Override
  public Enumeration getParameterNames() {
    return Collections.enumeration(this.parameters.keySet());
  }

  @Override
  public String[] getParameterValues(String name) {
    return (String[]) this.parameters.get(name);
  }

  @Override
  public Map getParameterMap() {
    return Collections.unmodifiableMap(this.parameters);
  }

  @Override
  public String getProtocol() {
    return this.protocol;
  }

  public void setProtocol(String protocol) {
    this.protocol = protocol;
  }

  @Override
  public String getScheme() {
    return this.scheme;
  }

  public void setScheme(String scheme) {
    this.scheme = scheme;
  }

  @Override
  public String getServerName() {
    return this.serverName;
  }

  public void setServerName(String serverName) {
    this.serverName = serverName;
  }

  @Override
  public int getServerPort() {
    return this.serverPort;
  }

  public void setServerPort(int serverPort) {
    this.serverPort = serverPort;
  }

  @Override
  public BufferedReader getReader() throws IOException {
    if (this.content != null) {
      InputStream sourceStream = new ByteArrayInputStream(this.content);
      Reader sourceReader =
          (this.characterEncoding != null)
              ? new InputStreamReader(sourceStream, this.characterEncoding)
              : new InputStreamReader(sourceStream);
      return new BufferedReader(sourceReader);
    } else {
      return null;
    }
  }

  @Override
  public String getRemoteAddr() {
    return this.remoteAddr;
  }

  public void setRemoteAddr(String remoteAddr) {
    this.remoteAddr = remoteAddr;
  }

  @Override
  public String getRemoteHost() {
    return this.remoteHost;
  }

  public void setRemoteHost(String remoteHost) {
    this.remoteHost = remoteHost;
  }

  @Override
  public void setAttribute(String name, Object value) {
    checkActive();
    if (value != null) {
      this.attributes.put(name, value);
    } else {
      this.attributes.remove(name);
    }
  }

  @Override
  public void removeAttribute(String name) {
    checkActive();
    this.attributes.remove(name);
  }

  public void clearAttributes() {
    this.attributes.clear();
  }

  public void addPreferredLocale(Locale locale) {
    this.locales.add(0, locale);
  }

  @Override
  public Locale getLocale() {
    return (Locale) this.locales.get(0);
  }

  @Override
  public Enumeration getLocales() {
    return this.locales.elements();
  }

  @Override
  public boolean isSecure() {
    return this.secure;
  }

  public void setSecure(boolean secure) {
    this.secure = secure;
  }

  @Override
  public RequestDispatcher getRequestDispatcher(String path) {
    return new CpfRequestDispatcher(path);
  }

  @Override
  public String getRealPath(String path) {
    return this.servletContext.getRealPath(path);
  }

  @Override
  public int getRemotePort() {
    return this.remotePort;
  }

  public void setRemotePort(int remotePort) {
    this.remotePort = remotePort;
  }

  @Override
  public String getLocalName() {
    return this.localName;
  }

  public void setLocalName(String localName) {
    this.localName = localName;
  }

  @Override
  public String getLocalAddr() {
    return this.localAddr;
  }

  public void setLocalAddr(String localAddr) {
    this.localAddr = localAddr;
  }

  @Override
  public int getLocalPort() {
    return this.localPort;
  }

  public void setLocalPort(int localPort) {
    this.localPort = localPort;
  }
}
  @SuppressWarnings("unchecked")
  protected Map convertToTypedMap(
      Map original, String propertyName, Class requiredType, TypeDescriptor typeDescriptor) {

    boolean originalAllowed = requiredType.isInstance(original);
    if (!originalAllowed && !Map.class.isAssignableFrom(requiredType)) {
      return original;
    }

    Class keyType = null;
    Class valueType = null;
    MethodParameter methodParam = typeDescriptor.getMethodParameter();
    if (methodParam != null) {
      keyType = GenericCollectionTypeResolver.getMapKeyParameterType(methodParam);
      valueType = GenericCollectionTypeResolver.getMapValueParameterType(methodParam);
    }
    if (keyType == null
        && valueType == null
        && originalAllowed
        && !this.propertyEditorRegistry.hasCustomEditorForElement(null, propertyName)) {
      return original;
    }

    Iterator it;
    try {
      it = original.entrySet().iterator();
      if (it == null) {
        if (logger.isDebugEnabled()) {
          logger.debug(
              "Map of type ["
                  + original.getClass().getName()
                  + "] returned null Iterator - injecting original Map as-is");
        }
        return original;
      }
    } catch (Throwable ex) {
      if (logger.isDebugEnabled()) {
        logger.debug(
            "Cannot access Map of type ["
                + original.getClass().getName()
                + "] - injecting original Map as-is",
            ex);
      }
      return original;
    }

    Map convertedCopy;
    try {
      if (CollectionFactory.isApproximableMapType(requiredType)) {
        convertedCopy = CollectionFactory.createApproximateMap(original, original.size());
      } else {
        convertedCopy = (Map) requiredType.newInstance();
      }
    } catch (Throwable ex) {
      if (logger.isDebugEnabled()) {
        logger.debug(
            "Cannot create copy of Map type ["
                + original.getClass().getName()
                + "] - injecting original Map as-is",
            ex);
      }
      return original;
    }

    while (it.hasNext()) {
      Map.Entry entry = (Map.Entry) it.next();
      Object key = entry.getKey();
      Object value = entry.getValue();
      String keyedPropertyName = buildKeyedPropertyName(propertyName, key);
      if (methodParam != null) {
        methodParam.increaseNestingLevel();
        methodParam.setTypeIndexForCurrentLevel(0);
      }
      Object convertedKey =
          convertIfNecessary(keyedPropertyName, null, key, keyType, typeDescriptor);
      if (methodParam != null) {
        methodParam.setTypeIndexForCurrentLevel(1);
      }
      Object convertedValue =
          convertIfNecessary(keyedPropertyName, null, value, valueType, typeDescriptor);
      if (methodParam != null) {
        methodParam.decreaseNestingLevel();
      }
      try {
        convertedCopy.put(convertedKey, convertedValue);
      } catch (Throwable ex) {
        if (logger.isDebugEnabled()) {
          logger.debug(
              "Map type ["
                  + original.getClass().getName()
                  + "] seems to be read-only - injecting original Map as-is",
              ex);
        }
        return original;
      }
      originalAllowed = originalAllowed && (key == convertedKey) && (value == convertedValue);
    }
    return (originalAllowed ? original : convertedCopy);
  }
  @SuppressWarnings("unchecked")
  protected Collection convertToTypedCollection(
      Collection original, String propertyName, Class requiredType, TypeDescriptor typeDescriptor) {

    boolean originalAllowed = requiredType.isInstance(original);
    if (!originalAllowed && !Collection.class.isAssignableFrom(requiredType)) {
      return original;
    }

    MethodParameter methodParam = typeDescriptor.getMethodParameter();
    Class elementType = null;
    if (methodParam != null) {
      elementType = GenericCollectionTypeResolver.getCollectionParameterType(methodParam);
    }
    if (elementType == null
        && originalAllowed
        && !this.propertyEditorRegistry.hasCustomEditorForElement(null, propertyName)) {
      return original;
    }

    Iterator it;
    try {
      it = original.iterator();
      if (it == null) {
        if (logger.isDebugEnabled()) {
          logger.debug(
              "Collection of type ["
                  + original.getClass().getName()
                  + "] returned null Iterator - injecting original Collection as-is");
        }
        return original;
      }
    } catch (Throwable ex) {
      if (logger.isDebugEnabled()) {
        logger.debug(
            "Cannot access Collection of type ["
                + original.getClass().getName()
                + "] - injecting original Collection as-is",
            ex);
      }
      return original;
    }

    Collection convertedCopy;
    try {
      if (CollectionFactory.isApproximableCollectionType(requiredType)) {
        convertedCopy = CollectionFactory.createApproximateCollection(original, original.size());
      } else {
        convertedCopy = (Collection) requiredType.newInstance();
      }
    } catch (Throwable ex) {
      if (logger.isDebugEnabled()) {
        logger.debug(
            "Cannot create copy of Collection type ["
                + original.getClass().getName()
                + "] - injecting original Collection as-is",
            ex);
      }
      return original;
    }

    int i = 0;
    for (; it.hasNext(); i++) {
      Object element = it.next();
      String indexedPropertyName = buildIndexedPropertyName(propertyName, i);
      if (methodParam != null) {
        methodParam.increaseNestingLevel();
      }
      Object convertedElement =
          convertIfNecessary(indexedPropertyName, null, element, elementType, typeDescriptor);
      if (methodParam != null) {
        methodParam.decreaseNestingLevel();
      }
      try {
        convertedCopy.add(convertedElement);
      } catch (Throwable ex) {
        if (logger.isDebugEnabled()) {
          logger.debug(
              "Collection type ["
                  + original.getClass().getName()
                  + "] seems to be read-only - injecting original Collection as-is",
              ex);
        }
        return original;
      }
      originalAllowed = originalAllowed && (element == convertedElement);
    }
    return (originalAllowed ? original : convertedCopy);
  }
  @SuppressWarnings("unchecked")
  private Map<?, ?> convertToTypedMap(
      Map<?, ?> original,
      String propertyName,
      Class<?> requiredType,
      TypeDescriptor typeDescriptor) {

    if (!Map.class.isAssignableFrom(requiredType)) {
      return original;
    }

    boolean approximable = CollectionFactory.isApproximableMapType(requiredType);
    if (!approximable && !canCreateCopy(requiredType)) {
      if (logger.isDebugEnabled()) {
        logger.debug(
            "Custom Map type ["
                + original.getClass().getName()
                + "] does not allow for creating a copy - injecting original Map as-is");
      }
      return original;
    }

    boolean originalAllowed = requiredType.isInstance(original);
    TypeDescriptor keyType = typeDescriptor.getMapKeyTypeDescriptor();
    TypeDescriptor valueType = typeDescriptor.getMapValueTypeDescriptor();
    if (keyType == null
        && valueType == null
        && originalAllowed
        && !this.propertyEditorRegistry.hasCustomEditorForElement(null, propertyName)) {
      return original;
    }

    Iterator<?> it;
    try {
      it = original.entrySet().iterator();
      if (it == null) {
        if (logger.isDebugEnabled()) {
          logger.debug(
              "Map of type ["
                  + original.getClass().getName()
                  + "] returned null Iterator - injecting original Map as-is");
        }
        return original;
      }
    } catch (Throwable ex) {
      if (logger.isDebugEnabled()) {
        logger.debug(
            "Cannot access Map of type ["
                + original.getClass().getName()
                + "] - injecting original Map as-is: "
                + ex);
      }
      return original;
    }

    Map<Object, Object> convertedCopy;
    try {
      if (approximable) {
        convertedCopy = CollectionFactory.createApproximateMap(original, original.size());
      } else {
        convertedCopy =
            (Map<Object, Object>) ReflectionUtils.accessibleConstructor(requiredType).newInstance();
      }
    } catch (Throwable ex) {
      if (logger.isDebugEnabled()) {
        logger.debug(
            "Cannot create copy of Map type ["
                + original.getClass().getName()
                + "] - injecting original Map as-is: "
                + ex);
      }
      return original;
    }

    while (it.hasNext()) {
      Map.Entry<?, ?> entry = (Map.Entry<?, ?>) it.next();
      Object key = entry.getKey();
      Object value = entry.getValue();
      String keyedPropertyName = buildKeyedPropertyName(propertyName, key);
      Object convertedKey =
          convertIfNecessary(
              keyedPropertyName, null, key, (keyType != null ? keyType.getType() : null), keyType);
      Object convertedValue =
          convertIfNecessary(
              keyedPropertyName,
              null,
              value,
              (valueType != null ? valueType.getType() : null),
              valueType);
      try {
        convertedCopy.put(convertedKey, convertedValue);
      } catch (Throwable ex) {
        if (logger.isDebugEnabled()) {
          logger.debug(
              "Map type ["
                  + original.getClass().getName()
                  + "] seems to be read-only - injecting original Map as-is: "
                  + ex);
        }
        return original;
      }
      originalAllowed = originalAllowed && (key == convertedKey) && (value == convertedValue);
    }
    return (originalAllowed ? original : convertedCopy);
  }
  @SuppressWarnings("unchecked")
  private Collection<?> convertToTypedCollection(
      Collection<?> original,
      String propertyName,
      Class<?> requiredType,
      TypeDescriptor typeDescriptor) {

    if (!Collection.class.isAssignableFrom(requiredType)) {
      return original;
    }

    boolean approximable = CollectionFactory.isApproximableCollectionType(requiredType);
    if (!approximable && !canCreateCopy(requiredType)) {
      if (logger.isDebugEnabled()) {
        logger.debug(
            "Custom Collection type ["
                + original.getClass().getName()
                + "] does not allow for creating a copy - injecting original Collection as-is");
      }
      return original;
    }

    boolean originalAllowed = requiredType.isInstance(original);
    TypeDescriptor elementType = typeDescriptor.getElementTypeDescriptor();
    if (elementType == null
        && originalAllowed
        && !this.propertyEditorRegistry.hasCustomEditorForElement(null, propertyName)) {
      return original;
    }

    Iterator<?> it;
    try {
      it = original.iterator();
      if (it == null) {
        if (logger.isDebugEnabled()) {
          logger.debug(
              "Collection of type ["
                  + original.getClass().getName()
                  + "] returned null Iterator - injecting original Collection as-is");
        }
        return original;
      }
    } catch (Throwable ex) {
      if (logger.isDebugEnabled()) {
        logger.debug(
            "Cannot access Collection of type ["
                + original.getClass().getName()
                + "] - injecting original Collection as-is: "
                + ex);
      }
      return original;
    }

    Collection<Object> convertedCopy;
    try {
      if (approximable) {
        convertedCopy = CollectionFactory.createApproximateCollection(original, original.size());
      } else {
        convertedCopy =
            (Collection<Object>) ReflectionUtils.accessibleConstructor(requiredType).newInstance();
      }
    } catch (Throwable ex) {
      if (logger.isDebugEnabled()) {
        logger.debug(
            "Cannot create copy of Collection type ["
                + original.getClass().getName()
                + "] - injecting original Collection as-is: "
                + ex);
      }
      return original;
    }

    int i = 0;
    for (; it.hasNext(); i++) {
      Object element = it.next();
      String indexedPropertyName = buildIndexedPropertyName(propertyName, i);
      Object convertedElement =
          convertIfNecessary(
              indexedPropertyName,
              null,
              element,
              (elementType != null ? elementType.getType() : null),
              elementType);
      try {
        convertedCopy.add(convertedElement);
      } catch (Throwable ex) {
        if (logger.isDebugEnabled()) {
          logger.debug(
              "Collection type ["
                  + original.getClass().getName()
                  + "] seems to be read-only - injecting original Collection as-is: "
                  + ex);
        }
        return original;
      }
      originalAllowed = originalAllowed && (element == convertedElement);
    }
    return (originalAllowed ? original : convertedCopy);
  }