View Javadoc
1   /*
2    * Copyright 2009-2010 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.springframework.batch.admin.web;
17  
18  import java.beans.PropertyEditor;
19  import java.io.IOException;
20  import java.util.Arrays;
21  import java.util.HashMap;
22  import java.util.List;
23  import java.util.Map;
24  
25  import org.springframework.beans.BeanWrapperImpl;
26  import org.springframework.beans.BeansException;
27  import org.springframework.beans.PropertyEditorRegistry;
28  import org.springframework.beans.factory.BeanFactory;
29  import org.springframework.beans.factory.BeanFactoryAware;
30  import org.springframework.beans.factory.support.AbstractBeanFactory;
31  import org.springframework.core.convert.converter.Converter;
32  import org.springframework.core.convert.support.GenericConversionService;
33  import org.springframework.http.HttpInputMessage;
34  import org.springframework.http.HttpOutputMessage;
35  import org.springframework.http.MediaType;
36  import org.springframework.http.converter.HttpMessageConverter;
37  import org.springframework.http.converter.HttpMessageNotReadableException;
38  import org.springframework.http.converter.HttpMessageNotWritableException;
39  import org.springframework.integration.http.converter.MultipartAwareFormHttpMessageConverter;
40  import org.springframework.util.MultiValueMap;
41  import org.springframework.web.multipart.MultipartFile;
42  
43  public class BindingHttpMessageConverter<T> implements HttpMessageConverter<T>, BeanFactoryAware {
44  
45  	private AbstractBeanFactory beanFactory;
46  
47  	private MultipartAwareFormHttpMessageConverter delegate = new MultipartAwareFormHttpMessageConverter();
48  
49  	private Class<T> targetType;
50  
51  	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
52  		this.beanFactory = (AbstractBeanFactory) beanFactory;
53  	}
54  
55  	/**
56  	 * @param targetType the tergetType to set
57  	 */
58  	public void setTargetType(Class<T> targetType) {
59  		this.targetType = targetType;
60  	}
61  
62  	public List<MediaType> getSupportedMediaTypes() {
63  		return Arrays.asList(MediaType.TEXT_PLAIN);
64  	}
65  
66  	public boolean canRead(Class<?> clazz, MediaType mediaType) {
67  		return clazz.isAssignableFrom(targetType);
68  	}
69  
70  	public boolean canWrite(Class<?> clazz, MediaType mediaType) {
71  		return false;
72  	}
73  
74  	public T read(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException,
75  			HttpMessageNotReadableException {
76  		MultiValueMap<String, ?> map = delegate.read(null, inputMessage);
77  		BeanWrapperImpl beanWrapper = new BeanWrapperImpl(targetType);
78  		initBeanWrapper(beanWrapper);
79  		Map<String, Object> props = new HashMap<String, Object>();
80  		for (String key : map.keySet()) {
81  			if (beanWrapper.isWritableProperty(key)) {
82  				List<?> list = map.get(key);
83  				props.put(key, map.get(key).size()>1 ? list : map.getFirst(key));
84  			}
85  		}
86  		beanWrapper.setPropertyValues(props);
87  		@SuppressWarnings("unchecked")
88  		T result = (T) beanWrapper.getWrappedInstance();
89  		return result;
90  	}
91  
92  	public void write(T input, MediaType contentType, HttpOutputMessage outputMessage) throws IOException,
93  			HttpMessageNotWritableException {
94  		throw new UnsupportedOperationException();
95  	}
96  
97  	private void initBeanWrapper(BeanWrapperImpl beanWrapper) {
98  
99  		GenericConversionService conversionService = new GenericConversionService();
100 		conversionService.addConverter(new MultipartFileConverter(beanWrapper));
101 
102 		beanWrapper.setConversionService(conversionService);
103 		if (beanFactory != null) {
104 			beanFactory.copyRegisteredEditorsTo(beanWrapper);
105 		}
106 
107 	}
108 
109 	private static class MultipartFileConverter implements Converter<MultipartFile, String> {
110 
111 		private final PropertyEditorRegistry accessor;
112 
113 		public MultipartFileConverter(PropertyEditorRegistry accessor) {
114 			this.accessor = accessor;
115 		}
116 
117 		public String convert(MultipartFile source) {
118 
119 			PropertyEditor editor = accessor.findCustomEditor(MultipartFile.class, null);
120 			if (editor == null) {
121 				throw new IllegalStateException("Cannot convert source of type " + source.getClass()
122 						+ " to type: String");
123 			}
124 			editor.setValue(source);
125 			return editor.getAsText();
126 		}
127 
128 	}
129 
130 }