提交 2c637dcb 编写于 作者: J Juergen Hoeller

ReaderEditor supports Reader injection analogous to InputStreamEditor (from...

ReaderEditor supports Reader injection analogous to InputStreamEditor (from Spring resource location)

Also, EncodedResource implements InputStreamSource now since it declares getInputStream() anyway.

Issue: SPR-12876
上级 ceb17fca
/* /*
* Copyright 2002-2014 the original author or authors. * Copyright 2002-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -19,6 +19,7 @@ package org.springframework.beans; ...@@ -19,6 +19,7 @@ package org.springframework.beans;
import java.beans.PropertyEditor; import java.beans.PropertyEditor;
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import java.net.URI; import java.net.URI;
...@@ -60,6 +61,7 @@ import org.springframework.beans.propertyeditors.InputStreamEditor; ...@@ -60,6 +61,7 @@ import org.springframework.beans.propertyeditors.InputStreamEditor;
import org.springframework.beans.propertyeditors.LocaleEditor; import org.springframework.beans.propertyeditors.LocaleEditor;
import org.springframework.beans.propertyeditors.PatternEditor; import org.springframework.beans.propertyeditors.PatternEditor;
import org.springframework.beans.propertyeditors.PropertiesEditor; import org.springframework.beans.propertyeditors.PropertiesEditor;
import org.springframework.beans.propertyeditors.ReaderEditor;
import org.springframework.beans.propertyeditors.StringArrayPropertyEditor; import org.springframework.beans.propertyeditors.StringArrayPropertyEditor;
import org.springframework.beans.propertyeditors.TimeZoneEditor; import org.springframework.beans.propertyeditors.TimeZoneEditor;
import org.springframework.beans.propertyeditors.URIEditor; import org.springframework.beans.propertyeditors.URIEditor;
...@@ -211,6 +213,7 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry { ...@@ -211,6 +213,7 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
this.defaultEditors.put(Locale.class, new LocaleEditor()); this.defaultEditors.put(Locale.class, new LocaleEditor());
this.defaultEditors.put(Pattern.class, new PatternEditor()); this.defaultEditors.put(Pattern.class, new PatternEditor());
this.defaultEditors.put(Properties.class, new PropertiesEditor()); this.defaultEditors.put(Properties.class, new PropertiesEditor());
this.defaultEditors.put(Reader.class, new ReaderEditor());
this.defaultEditors.put(Resource[].class, new ResourceArrayPropertyEditor()); this.defaultEditors.put(Resource[].class, new ResourceArrayPropertyEditor());
this.defaultEditors.put(TimeZone.class, new TimeZoneEditor()); this.defaultEditors.put(TimeZone.class, new TimeZoneEditor());
this.defaultEditors.put(URI.class, new URIEditor()); this.defaultEditors.put(URI.class, new URIEditor());
......
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -25,13 +25,13 @@ import org.springframework.util.Assert; ...@@ -25,13 +25,13 @@ import org.springframework.util.Assert;
/** /**
* One-way PropertyEditor which can convert from a text String to a * One-way PropertyEditor which can convert from a text String to a
* {@code java.io.InputStream}, interpreting the given String * {@code java.io.InputStream}, interpreting the given String as a
* as Spring resource location (e.g. a URL String). * Spring resource location (e.g. a URL String).
* *
* <p>Supports Spring-style URL notation: any fully qualified standard URL * <p>Supports Spring-style URL notation: any fully qualified standard URL
* ("file:", "http:", etc) and Spring's special "classpath:" pseudo-URL. * ("file:", "http:", etc) and Spring's special "classpath:" pseudo-URL.
* *
* <p>Note that in the default usage, the stream is not closed by Spring itself! * <p>Note that such streams do usually not get closed by Spring itself!
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 1.0.1 * @since 1.0.1
...@@ -73,8 +73,7 @@ public class InputStreamEditor extends PropertyEditorSupport { ...@@ -73,8 +73,7 @@ public class InputStreamEditor extends PropertyEditorSupport {
setValue(resource != null ? resource.getInputStream() : null); setValue(resource != null ? resource.getInputStream() : null);
} }
catch (IOException ex) { catch (IOException ex) {
throw new IllegalArgumentException( throw new IllegalArgumentException("Failed to retrieve InputStream for " + resource, ex);
"Could not retrieve InputStream for " + resource + ": " + ex.getMessage());
} }
} }
......
/*
* Copyright 2002-2015 the original author or authors.
*
* Licensed 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 org.springframework.beans.propertyeditors;
import java.beans.PropertyEditorSupport;
import java.io.IOException;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceEditor;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.util.Assert;
/**
* One-way PropertyEditor which can convert from a text String to a
* {@code java.io.Reader}, interpreting the given String as a Spring
* resource location (e.g. a URL String).
*
* <p>Supports Spring-style URL notation: any fully qualified standard URL
* ("file:", "http:", etc) and Spring's special "classpath:" pseudo-URL.
*
* <p>Note that such readers do usually not get closed by Spring itself!
*
* @author Juergen Hoeller
* @since 4.2
* @see java.io.Reader
* @see org.springframework.core.io.ResourceEditor
* @see org.springframework.core.io.ResourceLoader
* @see InputStreamEditor
*/
public class ReaderEditor extends PropertyEditorSupport {
private final ResourceEditor resourceEditor;
/**
* Create a new ReaderEditor,
* using the default ResourceEditor underneath.
*/
public ReaderEditor() {
this.resourceEditor = new ResourceEditor();
}
/**
* Create a new ReaderEditor,
* using the given ResourceEditor underneath.
* @param resourceEditor the ResourceEditor to use
*/
public ReaderEditor(ResourceEditor resourceEditor) {
Assert.notNull(resourceEditor, "ResourceEditor must not be null");
this.resourceEditor = resourceEditor;
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
this.resourceEditor.setAsText(text);
Resource resource = (Resource) this.resourceEditor.getValue();
try {
setValue(resource != null ? new EncodedResource(resource).getReader() : null);
}
catch (IOException ex) {
throw new IllegalArgumentException("Failed to retrieve Reader for " + resource, ex);
}
}
/**
* This implementation returns {@code null} to indicate that
* there is no appropriate text representation.
*/
@Override
public String getAsText() {
return null;
}
}
/* /*
* Copyright 2002-2014 the original author or authors. * Copyright 2002-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -19,6 +19,7 @@ package org.springframework.beans.support; ...@@ -19,6 +19,7 @@ package org.springframework.beans.support;
import java.beans.PropertyEditor; import java.beans.PropertyEditor;
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;
import java.io.Reader;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
...@@ -32,10 +33,10 @@ import org.springframework.beans.propertyeditors.ClassEditor; ...@@ -32,10 +33,10 @@ import org.springframework.beans.propertyeditors.ClassEditor;
import org.springframework.beans.propertyeditors.FileEditor; import org.springframework.beans.propertyeditors.FileEditor;
import org.springframework.beans.propertyeditors.InputSourceEditor; import org.springframework.beans.propertyeditors.InputSourceEditor;
import org.springframework.beans.propertyeditors.InputStreamEditor; import org.springframework.beans.propertyeditors.InputStreamEditor;
import org.springframework.beans.propertyeditors.ReaderEditor;
import org.springframework.beans.propertyeditors.URIEditor; import org.springframework.beans.propertyeditors.URIEditor;
import org.springframework.beans.propertyeditors.URLEditor; import org.springframework.beans.propertyeditors.URLEditor;
import org.springframework.core.env.PropertyResolver; import org.springframework.core.env.PropertyResolver;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.ContextResource; import org.springframework.core.io.ContextResource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceEditor; import org.springframework.core.io.ResourceEditor;
...@@ -102,6 +103,7 @@ public class ResourceEditorRegistrar implements PropertyEditorRegistrar { ...@@ -102,6 +103,7 @@ public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor)); doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor)); doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
doRegisterEditor(registry, File.class, new FileEditor(baseEditor)); doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor));
doRegisterEditor(registry, URL.class, new URLEditor(baseEditor)); doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));
ClassLoader classLoader = this.resourceLoader.getClassLoader(); ClassLoader classLoader = this.resourceLoader.getClassLoader();
......
/* /*
* Copyright 2002-2006 the original author or authors. * Copyright 2002-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -30,9 +30,9 @@ import static org.junit.Assert.*; ...@@ -30,9 +30,9 @@ import static org.junit.Assert.*;
* @author Rick Evans * @author Rick Evans
* @author Chris Beams * @author Chris Beams
*/ */
public final class InputStreamEditorTests { public class InputStreamEditorTests {
@Test(expected=IllegalArgumentException.class) @Test(expected = IllegalArgumentException.class)
public void testCtorWithNullResourceEditor() throws Exception { public void testCtorWithNullResourceEditor() throws Exception {
new InputStreamEditor(null); new InputStreamEditor(null);
} }
...@@ -41,7 +41,8 @@ public final class InputStreamEditorTests { ...@@ -41,7 +41,8 @@ public final class InputStreamEditorTests {
public void testSunnyDay() throws Exception { public void testSunnyDay() throws Exception {
InputStream stream = null; InputStream stream = null;
try { try {
String resource = "classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/" + ClassUtils.getShortName(getClass()) + ".class"; String resource = "classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) +
"/" + ClassUtils.getShortName(getClass()) + ".class";
InputStreamEditor editor = new InputStreamEditor(); InputStreamEditor editor = new InputStreamEditor();
editor.setAsText(resource); editor.setAsText(resource);
Object value = editor.getValue(); Object value = editor.getValue();
...@@ -49,14 +50,15 @@ public final class InputStreamEditorTests { ...@@ -49,14 +50,15 @@ public final class InputStreamEditorTests {
assertTrue(value instanceof InputStream); assertTrue(value instanceof InputStream);
stream = (InputStream) value; stream = (InputStream) value;
assertTrue(stream.available() > 0); assertTrue(stream.available() > 0);
} finally { }
finally {
if (stream != null) { if (stream != null) {
stream.close(); stream.close();
} }
} }
} }
@Test(expected=IllegalArgumentException.class) @Test(expected = IllegalArgumentException.class)
public void testWhenResourceDoesNotExist() throws Exception { public void testWhenResourceDoesNotExist() throws Exception {
String resource = "classpath:bingo!"; String resource = "classpath:bingo!";
InputStreamEditor editor = new InputStreamEditor(); InputStreamEditor editor = new InputStreamEditor();
...@@ -66,7 +68,8 @@ public final class InputStreamEditorTests { ...@@ -66,7 +68,8 @@ public final class InputStreamEditorTests {
@Test @Test
public void testGetAsTextReturnsNullByDefault() throws Exception { public void testGetAsTextReturnsNullByDefault() throws Exception {
assertNull(new InputStreamEditor().getAsText()); assertNull(new InputStreamEditor().getAsText());
String resource = "classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/" + ClassUtils.getShortName(getClass()) + ".class"; String resource = "classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) +
"/" + ClassUtils.getShortName(getClass()) + ".class";
InputStreamEditor editor = new InputStreamEditor(); InputStreamEditor editor = new InputStreamEditor();
editor.setAsText(resource); editor.setAsText(resource);
assertNull(editor.getAsText()); assertNull(editor.getAsText());
......
/*
* Copyright 2002-2015 the original author or authors.
*
* Licensed 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 org.springframework.beans.propertyeditors;
import java.io.Reader;
import org.junit.Test;
import org.springframework.util.ClassUtils;
import static org.junit.Assert.*;
/**
* Unit tests for the {@link ReaderEditor} class.
*
* @author Juergen Hoeller
* @since 4.2
*/
public class ReaderEditorTests {
@Test(expected = IllegalArgumentException.class)
public void testCtorWithNullResourceEditor() throws Exception {
new InputStreamEditor(null);
}
@Test
public void testSunnyDay() throws Exception {
Reader reader = null;
try {
String resource = "classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) +
"/" + ClassUtils.getShortName(getClass()) + ".class";
ReaderEditor editor = new ReaderEditor();
editor.setAsText(resource);
Object value = editor.getValue();
assertNotNull(value);
assertTrue(value instanceof Reader);
reader = (Reader) value;
assertTrue(reader.ready());
}
finally {
if (reader != null) {
reader.close();
}
}
}
@Test(expected = IllegalArgumentException.class)
public void testWhenResourceDoesNotExist() throws Exception {
String resource = "classpath:bingo!";
ReaderEditor editor = new ReaderEditor();
editor.setAsText(resource);
}
@Test
public void testGetAsTextReturnsNullByDefault() throws Exception {
assertNull(new ReaderEditor().getAsText());
String resource = "classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) +
"/" + ClassUtils.getShortName(getClass()) + ".class";
ReaderEditor editor = new ReaderEditor();
editor.setAsText(resource);
assertNull(editor.getAsText());
}
}
...@@ -16,7 +16,13 @@ ...@@ -16,7 +16,13 @@
package org.springframework.context.expression; package org.springframework.context.expression;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.Serializable; import java.io.Serializable;
import java.net.URI;
import java.net.URL;
import java.security.AccessControlException; import java.security.AccessControlException;
import java.security.Permission; import java.security.Permission;
import java.util.Properties; import java.util.Properties;
...@@ -36,13 +42,18 @@ import org.springframework.beans.factory.support.AutowireCandidateQualifier; ...@@ -36,13 +42,18 @@ import org.springframework.beans.factory.support.AutowireCandidateQualifier;
import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.AnnotationConfigUtils; import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.support.GenericApplicationContext; import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.GenericConversionService; import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.tests.Assume; import org.springframework.tests.Assume;
import org.springframework.tests.TestGroup; import org.springframework.tests.TestGroup;
import org.springframework.tests.sample.beans.TestBean; import org.springframework.tests.sample.beans.TestBean;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.SerializationTestUtils; import org.springframework.util.SerializationTestUtils;
import org.springframework.util.StopWatch; import org.springframework.util.StopWatch;
...@@ -56,6 +67,7 @@ public class ApplicationContextExpressionTests { ...@@ -56,6 +67,7 @@ public class ApplicationContextExpressionTests {
private static final Log factoryLog = LogFactory.getLog(DefaultListableBeanFactory.class); private static final Log factoryLog = LogFactory.getLog(DefaultListableBeanFactory.class);
@Test @Test
public void genericApplicationContext() throws Exception { public void genericApplicationContext() throws Exception {
GenericApplicationContext ac = new GenericApplicationContext(); GenericApplicationContext ac = new GenericApplicationContext();
...@@ -312,6 +324,27 @@ public class ApplicationContextExpressionTests { ...@@ -312,6 +324,27 @@ public class ApplicationContextExpressionTests {
assertTrue(str.startsWith("test-")); assertTrue(str.startsWith("test-"));
} }
@Test
public void resourceInjection() throws IOException {
System.setProperty("logfile", "log4j.properties");
try {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(ResourceInjectionBean.class);
ResourceInjectionBean resourceInjectionBean = ac.getBean(ResourceInjectionBean.class);
Resource resource = new ClassPathResource("log4j.properties");
assertEquals(resource, resourceInjectionBean.resource);
assertEquals(resource.getURL(), resourceInjectionBean.url);
assertEquals(resource.getURI(), resourceInjectionBean.uri);
assertEquals(resource.getFile(), resourceInjectionBean.file);
assertArrayEquals(FileCopyUtils.copyToByteArray(resource.getInputStream()),
FileCopyUtils.copyToByteArray(resourceInjectionBean.inputStream));
assertEquals(FileCopyUtils.copyToString(new EncodedResource(resource).getReader()),
FileCopyUtils.copyToString(resourceInjectionBean.reader));
}
finally {
System.getProperties().remove("logfile");
}
}
@SuppressWarnings("serial") @SuppressWarnings("serial")
public static class ValueTestBean implements Serializable { public static class ValueTestBean implements Serializable {
...@@ -450,4 +483,26 @@ public class ApplicationContextExpressionTests { ...@@ -450,4 +483,26 @@ public class ApplicationContextExpressionTests {
} }
} }
public static class ResourceInjectionBean {
@Value("classpath:#{systemProperties.logfile}")
Resource resource;
@Value("classpath:#{systemProperties.logfile}")
URL url;
@Value("classpath:#{systemProperties.logfile}")
URI uri;
@Value("classpath:#{systemProperties.logfile}")
File file;
@Value("classpath:#{systemProperties.logfile}")
InputStream inputStream;
@Value("classpath:#{systemProperties.logfile}")
Reader reader;
}
} }
...@@ -22,6 +22,7 @@ import java.io.InputStreamReader; ...@@ -22,6 +22,7 @@ import java.io.InputStreamReader;
import java.io.Reader; import java.io.Reader;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import org.springframework.core.io.InputStreamSource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
...@@ -39,7 +40,7 @@ import org.springframework.util.ObjectUtils; ...@@ -39,7 +40,7 @@ import org.springframework.util.ObjectUtils;
* @see java.io.Reader * @see java.io.Reader
* @see java.nio.charset.Charset * @see java.nio.charset.Charset
*/ */
public class EncodedResource { public class EncodedResource implements InputStreamSource {
private final Resource resource; private final Resource resource;
...@@ -85,6 +86,7 @@ public class EncodedResource { ...@@ -85,6 +86,7 @@ public class EncodedResource {
this.charset = charset; this.charset = charset;
} }
/** /**
* Return the {@code Resource} held by this {@code EncodedResource}. * Return the {@code Resource} held by this {@code EncodedResource}.
*/ */
...@@ -146,6 +148,7 @@ public class EncodedResource { ...@@ -146,6 +148,7 @@ public class EncodedResource {
* @see #requiresReader() * @see #requiresReader()
* @see #getReader() * @see #getReader()
*/ */
@Override
public InputStream getInputStream() throws IOException { public InputStream getInputStream() throws IOException {
return this.resource.getInputStream(); return this.resource.getInputStream();
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册