001/*
002 * Copyright 2002-2016 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.beans.support;
018
019import java.beans.PropertyEditor;
020import java.io.File;
021import java.io.InputStream;
022import java.io.Reader;
023import java.net.URI;
024import java.net.URL;
025
026import org.xml.sax.InputSource;
027
028import org.springframework.beans.PropertyEditorRegistrar;
029import org.springframework.beans.PropertyEditorRegistry;
030import org.springframework.beans.PropertyEditorRegistrySupport;
031import org.springframework.beans.propertyeditors.ClassArrayEditor;
032import org.springframework.beans.propertyeditors.ClassEditor;
033import org.springframework.beans.propertyeditors.FileEditor;
034import org.springframework.beans.propertyeditors.InputSourceEditor;
035import org.springframework.beans.propertyeditors.InputStreamEditor;
036import org.springframework.beans.propertyeditors.PathEditor;
037import org.springframework.beans.propertyeditors.ReaderEditor;
038import org.springframework.beans.propertyeditors.URIEditor;
039import org.springframework.beans.propertyeditors.URLEditor;
040import org.springframework.core.env.PropertyResolver;
041import org.springframework.core.io.ContextResource;
042import org.springframework.core.io.Resource;
043import org.springframework.core.io.ResourceEditor;
044import org.springframework.core.io.ResourceLoader;
045import org.springframework.core.io.support.ResourceArrayPropertyEditor;
046import org.springframework.core.io.support.ResourcePatternResolver;
047import org.springframework.util.ClassUtils;
048
049/**
050 * PropertyEditorRegistrar implementation that populates a given
051 * {@link org.springframework.beans.PropertyEditorRegistry}
052 * (typically a {@link org.springframework.beans.BeanWrapper} used for bean
053 * creation within an {@link org.springframework.context.ApplicationContext})
054 * with resource editors. Used by
055 * {@link org.springframework.context.support.AbstractApplicationContext}.
056 *
057 * @author Juergen Hoeller
058 * @author Chris Beams
059 * @since 2.0
060 */
061public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
062
063        private static Class<?> pathClass;
064
065        static {
066                try {
067                        pathClass = ClassUtils.forName("java.nio.file.Path", ResourceEditorRegistrar.class.getClassLoader());
068                }
069                catch (ClassNotFoundException ex) {
070                        // Java 7 Path class not available
071                        pathClass = null;
072                }
073        }
074
075
076        private final PropertyResolver propertyResolver;
077
078        private final ResourceLoader resourceLoader;
079
080
081        /**
082         * Create a new ResourceEditorRegistrar for the given {@link ResourceLoader}
083         * and {@link PropertyResolver}.
084         * @param resourceLoader the ResourceLoader (or ResourcePatternResolver)
085         * to create editors for (usually an ApplicationContext)
086         * @param propertyResolver the PropertyResolver (usually an Environment)
087         * @see org.springframework.core.env.Environment
088         * @see org.springframework.core.io.support.ResourcePatternResolver
089         * @see org.springframework.context.ApplicationContext
090         */
091        public ResourceEditorRegistrar(ResourceLoader resourceLoader, PropertyResolver propertyResolver) {
092                this.resourceLoader = resourceLoader;
093                this.propertyResolver = propertyResolver;
094        }
095
096
097        /**
098         * Populate the given {@code registry} with the following resource editors:
099         * ResourceEditor, InputStreamEditor, InputSourceEditor, FileEditor, URLEditor,
100         * URIEditor, ClassEditor, ClassArrayEditor.
101         * <p>If this registrar has been configured with a {@link ResourcePatternResolver},
102         * a ResourceArrayPropertyEditor will be registered as well.
103         * @see org.springframework.core.io.ResourceEditor
104         * @see org.springframework.beans.propertyeditors.InputStreamEditor
105         * @see org.springframework.beans.propertyeditors.InputSourceEditor
106         * @see org.springframework.beans.propertyeditors.FileEditor
107         * @see org.springframework.beans.propertyeditors.URLEditor
108         * @see org.springframework.beans.propertyeditors.URIEditor
109         * @see org.springframework.beans.propertyeditors.ClassEditor
110         * @see org.springframework.beans.propertyeditors.ClassArrayEditor
111         * @see org.springframework.core.io.support.ResourceArrayPropertyEditor
112         */
113        @Override
114        public void registerCustomEditors(PropertyEditorRegistry registry) {
115                ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver);
116                doRegisterEditor(registry, Resource.class, baseEditor);
117                doRegisterEditor(registry, ContextResource.class, baseEditor);
118                doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
119                doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
120                doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
121                if (pathClass != null) {
122                        doRegisterEditor(registry, pathClass, new PathEditor(baseEditor));
123                }
124                doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor));
125                doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));
126
127                ClassLoader classLoader = this.resourceLoader.getClassLoader();
128                doRegisterEditor(registry, URI.class, new URIEditor(classLoader));
129                doRegisterEditor(registry, Class.class, new ClassEditor(classLoader));
130                doRegisterEditor(registry, Class[].class, new ClassArrayEditor(classLoader));
131
132                if (this.resourceLoader instanceof ResourcePatternResolver) {
133                        doRegisterEditor(registry, Resource[].class,
134                                        new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader, this.propertyResolver));
135                }
136        }
137
138        /**
139         * Override default editor, if possible (since that's what we really mean to do here);
140         * otherwise register as a custom editor.
141         */
142        private void doRegisterEditor(PropertyEditorRegistry registry, Class<?> requiredType, PropertyEditor editor) {
143                if (registry instanceof PropertyEditorRegistrySupport) {
144                        ((PropertyEditorRegistrySupport) registry).overrideDefaultEditor(requiredType, editor);
145                }
146                else {
147                        registry.registerCustomEditor(requiredType, editor);
148                }
149        }
150
151}